【问题标题】:Alternatives to decorator pattern装饰器模式的替代品
【发布时间】:2009-08-08 18:01:39
【问题描述】:

我发现装饰器模式最令人困惑。请考虑“Head first design patterns book”中提供的示例。

所以要得到一个带有双摩卡和鞭子的DarkRoast,你必须写

Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2);                                       
beverage2 = new Mocha(beverage2);                                       
beverage2 = new Whip(beverage2); 

我觉得这是不必要的。这是我的实现,

interface Beverage
{
   int Cost();
}

class DarkRoast : Beverage
{
   /* .... */
}

class Mocha : Beverage
{
   /* .... */
}

class Whip : Beverage
{
   /* .... */
}

// here is the changed part
class Order
{
    List<Beverage> beverages = new List<Beverage> beverages();
    public void AddItem(Beverage b)
    {
        beverages.Add(b);
    }

    public int Cost()
    {
        int cost;
        foreach(Beverage b in beverages)
            cost += b.Cost();
    }
}

// use it like
Order order = new Order();
order.AddItem(new DarkRoast());
order.AddItem(new Mocha());
order.AddItem(new Mocha());
order.AddItem(new Whip());
int cost = order.Cost();

IMO,两者都一样。如果是,这里使用装饰器模式有什么好处?

有什么想法吗?

【问题讨论】:

    标签: c# java design-patterns


    【解决方案1】:

    不,它们不一样。

    Head First 示例有 1 杯添加了 Mocha、Whip、Roast 的饮品。您的示例有 3 种饮料。
    请参阅此 Head First 代码。它适用于饮料的同一实例

    beverage2 = new Mocha(beverage2);                                       
    beverage2 = new DarkRoast(beverage2);                                       
    beverage2 = new Whip(beverage2);
    

    您的代码创建了 3 种饮料(这意味着有人分别订购了 3 种东西)。
    在现实生活中,我猜它不是饮料。饮料是一种,并在其上添加了香料。

    装饰器的目的是——装饰。 .Net 有 TextWriter 和 IndentedTextWriter (我猜),它基本上采用你的普通文本并对其应用缩进。如果你想的话,它在某种程度上类似于 unix 管道。

    输入 -> 调整 -> 调整输入 -> 进一步调整 -> 进一步调整输入。
    当前操作的输出成为下一个操作的输入。

    不知道我解释的好不好。

    【讨论】:

    • 请参阅此 Head First 代码。它适用于饮料的同一个实例。 它不是同一个实例。每个后续装饰器都采用前一个装饰器的实例。它是同一个变量,但分配了不同的实例。
    • @CodingYoshi:是的。我的意思是使用相同的变量,并且新实例包装现有实例以创建新饮料。谢谢你:)
    • @EdwardOlamisan:OP 展示了装饰器的可能替代方案,而不是要求替代方案。
    【解决方案2】:

    装饰器模式的重点是通过对象组合而不是继承来添加职责。继承是静态的,obj。构图是动态的,更灵活。装饰的可能性是无穷无尽的。也可以在运行时取消装饰对象。

    【讨论】:

    • 你能提供更多关于取消装饰的想法吗?
    【解决方案3】:

    我认为你实际上代表的是完全不同的东西。

    在您的示例中,您有一个接收饮料的对象调用订单,而在 Head first 示例中,他们只是用浇头装饰饮料,这会导致以下主要问题。

    在您的订单代码中,您可以放置​​多个饮料,如果可以,并且您放置多个浇头,每种饮料的浇头是什么?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-08
      • 1970-01-01
      • 1970-01-01
      • 2013-05-07
      • 1970-01-01
      相关资源
      最近更新 更多