实际使用国家或战略模式

时间:2013-06-26 15:08:28

标签: design-patterns

我的代码中有这个

switch (auctionType)
                {
                    case AuctionTypes.OpenBid:
                        destination = new EnglishAuction();
                        break;
                    case AuctionTypes.FixedPrice:
                        destination = new BuyoutAuction();
                        break;
                    case AuctionTypes.ClosedBid:
                        destination = new SealedFirstPriceAuction();
                        break;
                    default:
                        destination = new Auction();
                        break;
                }

我想知道的是如何使用策略或状态模式消除switch语句?

2 个答案:

答案 0 :(得分:3)

您发布的代码确实是工厂。在工厂里,开关都可以。

您返回的Auction个对象可能属于策略。战略和国家之间的区别是微妙的,但很重要:

  • 策略中,您使用不同的算法来完成本质上相同的事情。调用者不必知道这一点,这是一个实现细节。战略的一些例子可能是

    • 在电脑游戏中,你希望你的AI坏人攻击玩家。不同的敌人可能会使用不同的策略,因为他们可能会越过障碍物,传送到玩家或具有不同的战斗风格。
    • HybridDictionary中,操作可以在简单的ListDictionary中实现,而集合很小,并且在集合增长时使用Hashtable
    • 在CAD应用程序中,您可能已经实施了不同的策略来根据各种因素计算复杂方程的解,以找到最佳的速度与精度水平。

    这有时会导致混乱,因为不同怪物的行为是“明显的”或至少对最终用户可见,而后者则不然。另一方面, 可见,因为它希望更快/更精确。通常情况下,这并不是那么明显。

  • 状态模式中,另一方面,类的行为会有所不同。经典状态模式示例是TcpSocket类:套接字可以是连接或断开状态。这对客户端是可见的,并且在断开连接的套接字上调用Disconnect()是一个错误,就像在已连接的套接字上调用Connect()一样。对象本身可以改变其状态,并且它是可见的并且是外部已知的。

由于您使用的是工厂,因此返回的Auction对象在其生命周期内可能不会更改类型,这是正常操作的一部分。国家的实施通常不通过工厂,因为它们不可互换。相反,您可以在内部使用TcpSocket创建TcpSocketClosed,并在成功调用TcpSocketConnected后更改为Connect()

答案 1 :(得分:1)

只是为了好玩,并且参考@Raphaël关于在Java中消除switch语句的方法的评论,你可以在C#中获得类似的结果(虽然有更多的工作),如下所示:

创建一个包含Type的属性,并使用其无参数构造函数创建它的实例:

public class TypeAttribute : Attribute
{
    private readonly Type _type;

    public TypeAttribute(Type type)
    {
        _type = type;
    }

    public T CreateInstance()
    {
        return (T)Activator.CreateInstance(_type);
    }
}

...用属性

装饰你的enum
public enum AuctionTypes
{
    [Type(typeof(EnglishAuction))]
    OpenBid,

    [Type(typeof(BuyoutAuction))]
    FixedPrice,

    [Type(typeof(SealedFirstPriceAuction))]
    ClosedBid,

    [Type(typeof(Auction))]
    Default
}

...添加扩展方法:

public static class Extensions
{
    public static Auction CreateAuction(this AuctionTypes auctionType)
    {
        return typeof(AuctionTypes)
            .GetMember(auctionType.ToString())
            .First()
            .GetCustomAttributes(typeof(TypeAttribute), inherit: false)
            .Cast<TypeAttribute>()
            .First()
            .CreateInstance<Auction>();
    }
}

...你可以这样打电话:

var auction = auctionType.CreateAuction();

这是来自内存的,如果我们有通用属性会更好,但你去了。