2014-01-10 54 views
2

我试图实现工厂模式,并遇到问题。我尝试让我的课程变得简单。基本上我有一个基类数据包类(PacketHeader)与一些领域和方法。我还有很多派生的数据包类,例如:InfoPacket1011,UsagePacket1011,InfoPacket1014,UsagePacket1014,它们都从PacketHeader基类继承而来。使用不同的返回类型实现工厂模式

正如你所看到的每个数据包都有一个版本,我的目标是根据它们的版本来处理这些数据包。 (!这本身就是一个派生类),所以我应该有两个派生类,一个是1011,一个用于1014

的基类看起来是这样的:

public abstract class PacketHandlerBase : Engine 
{ 
    public abstract bool SendInfoPacket(int someInt, string someInput); 
    public abstract List<???> BuildInfoPacket(string someInput); 

    public abstract bool SendUsagePacket(int someInt, string someInput); 
    public abstract List<???> BuildUsagePacket(string someInput); 
    //... 
    //... 
    //... 
} 

我的问题是,这样的方法作为BuildInfoPacket和BuildUsagePacket我必须返回该类型的列表。所以在派生类中我可以有:

public class PacketHandler1011 : PackerHandlerBase 
{ 
    //... 
    public override bool SendInfoPacket(int someInt, string someInput); 
    { 
     // code implementation 
     // return true or false 
    } 

    public override List<InfoPacket1011> BuildInfoPacket(string someInput); 
    { 
     // code implementation 
     // return List<InfoPacket1011> 
    } 
} 

public class PacketHandler1014 : PackerHandlerBase 
{ 
    //... 
    public override bool SendInfoPacket(int someInt, string someInput); 
    { 
     // code implementation 
     // return true or false 
    } 

    public override List<InfoPacket1014> BuildInfoPacket(string someInput); 
    { 
     // code implementation 
     // return List<InfoPacket1014> 
    } 
} 

我不知道在PacketHandlerBase类使用什么能够覆盖它的派生类。我想我需要泛型方法和接口,但不知道如何处理。

[编辑]:我修复了关于数据包继承问题的第一部分。谢谢大家的回答,我阅读并告诉你它们是否有效。

[解答]:谢谢大家的回复。我通过传递List并将其转换为方法和调用者来解决问题。那么我的代码比我在这里提供的更复杂,我刚完成修改它。我也改变了抽象工厂的模式来解决一些其他问题。

任何帮助将不胜感激。 在此先感谢

+0

列表? – felipekm

回答

1

您在事实上实现一个Abstract Factory图案,其中PackerHandlerBase抽象工厂和它产生/建立一个抽象产品而你的情况是InfoPacketUsagePacket混凝土厂PacketHandler1011PacketHandler1014。而混凝土产品InfoPacket1011InfoPacket1014等。

所以它应该是:

public abstract class PacketHandlerBase : Engine 
{ 
    public abstract bool SendInfoPacket(int someInt, string someInput); 
    public abstract List<InfoPacket> BuildInfoPacket(string someInput); 

    public abstract bool SendUsagePacket(int someInt, string someInput); 
    public abstract List<UsagePacker> BuildUsagePacket(string someInput); 
    //... 
} 

public class InfoPacket1014 : InfoPacket 
{ 
    ///... 
} 

public class PacketHandler1011 : PackerHandlerBase 
{ 
    //... 
    public override List<InfoPacket> BuildInfoPacket(string someInput); 
    { 
     // code implementation 
     return new List<InfoPacket> { new InfoPacket1011(), ... }; 
    } 
} 
0

下面是一个例子使用它一般方法: 使用您的实体一样类型的约束:

where T : InfoPacketBase和派生类的方法:List<InfoPacket1011>;

abstract class A 
{ 
    public abstract List<T> BuildInfoPacket<T>(string someInput) where T : new(); 
} 

class B : A 
{ 
    public override List<T> BuildInfoPacket<T>(string someInput) 
    { 
     // code implementation 
     return new List<T> { new T() }; 
    } 

    public void Test() 
    { 
     BuildInfoPacket<object>("test"); 
    } 
} 
+0

这将不会编译。你是不是想让这个方法具有通用性? – svick

+0

是的,确切地说。我的错误,我修好了。 – speti43

3

在基类中所有的方法应该返回InfoPacketBase以及创建数据包使用如UsagePacketBase一个基类,你需要看一看polymorphism

public abstract class PacketHandlerBase : Engine 
{ 
    public abstract bool SendInfoPacket(int someInt, string someInput); 
    public abstract List<PackeHeader> BuildInfoPacket(string someInput); 

    public abstract bool SendUsagePacket(int someInt, string someInput); 
    public abstract List<PackeHeader> BuildUsagePacket(string someInput); 
    //... 
    //... 
    //... 
} 
+0

谢谢Julie, 那是我使用继承的首选方式!但是我正在修改别人的代码,我不能(不可能)改变数据包的继承。我有一个PackeHeader和所有其他数据包从此基类继承。 – Kian

+0

所以你可以使用PacketHeader而不是InfoPacketBase或UsagePacketBase看看我的答案它现在更新 –

+0

再次感谢Julie, 我曾尝试过,但我遇到了问题,显然我的问题与不当铸造有关。我用你的答案和Konard的答案结合解决了这个问题。 – Kian

0

如何:

public abstract class PacketHandlerBase<TInfoPacket, TUsagePacket> : Engine 
    where TInfoPacket : IInfoPacket 
    where TUsagePacket : IUsagePacket 
{ 
    public abstract bool SendInfoPacket(int someInt, string someInput); 
    public abstract List<TInfoPacket> BuildInfoPacket(string someInput); 

    public abstract bool SendUsagePacket(int someInt, string someInput); 
    public abstract List<TUsagePacket > BuildUsagePacket(string someInput); 
} 

您确保您的信息包类实现IInfoPacket接口。例如:

public InfoPacket1101 : PacketHeader, IInfoPacket 
{ 
    ... 
} 

类似地,所有使用分组类实现IUsagePacket。然后,你可以写你的数据包处理程序的给定版本,像这样:

public class PacketHandler1011 : PackerHandlerBase<InfoPacket1101, UsagePacket1101> 
{ 
    ... 
} 

我认为这是首选的解决方案,因为它意味着你可以对返回的对象更强的保证。只有一个基类,就像在当前接受的答案中那样,你不能在没有强制转换的情况下调用BuildInfoPacket返回的对象上的任何“信息包”特定的方法。与使用数据包类似。在这个解决方案中,IInfoPacket接口可以有方法,然后您可以调用而不需要投射。

+1

我的意思是理想情况下,您只需定义一个类型参数TPacket,然后该方法声明将为“public abstract List BuildInfoPacket(string someInput);”但C#不支持这种类型的混合。 –

+0

谢谢马丁, 我的问题是,所有的数据包从PacketHeader基类继承,并没有办法改变这种继承。 – Kian

+0

这不是一个问题:而不是InfoPacketBase等使用接口。我已经更新了我的答案以反映这一点。 –

0

,如果你不理解他们,并充分认识到自己的缺点的,不要使用泛型。在这种情况下,您可以返回IEnumerable<PacketHeader>并让多态性解决休息。

public abstract class PacketHandlerBase : Engine 
{ 
    public abstract bool SendInfoPacket(int someInt, string someInput); 
    public abstract IEnumerable<PacketHeader> BuildInfoPacket(string someInput); 

    public abstract bool SendUsagePacket(int someInt, string someInput); 
    public abstract IEnumerable<PacketHeader> BuildUsagePacket(string someInput); 
    //... 
    //... 
    //... 
} 

public class PacketHandler1011 : PackerHandlerBase 
{ 
    //... 
    public override bool SendInfoPacket(int someInt, string someInput); 
    { 
     // code implementation 
     // return true or false 
    } 

    public override IEnumerable<PacketHeader> BuildInfoPacket(string someInput); 
    { 
     yield return new InfoPacket1011(..) 
     // code implementation 
     // return List<InfoPacket1011> 
    } 
}