使用不同的返回类型实现工厂模式

时间:2014-01-10 15:39:58

标签: c# generics abstract-class factory

我正在尝试实施工厂模式,但遇到了问题。我试着让我的课程变得简单。基本上我有一个基本的Packet类(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等方法,我必须返回该类型的List。所以在派生类中我可以:

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并将其强制转换为方法和调用者来解决问题。好吧,我的代码比我在这里提供的代码复杂得多,我刚刚修改完它。我也将模式改为抽象工厂,以解决其他一些问题。

非常感谢任何帮助。 提前致谢

5 个答案:

答案 0 :(得分: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);
    //...
    //...
    //...
}

答案 1 :(得分: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(), ... };
    }
}

答案 2 :(得分: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");
    }
}

答案 3 :(得分: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接口可以具有您无需强制转换即可调用的方法。

答案 4 :(得分: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>
    }
}