要理解装饰师模式,让我们考虑一个灵感来自于书的“首部设计模式”。假设我们正在为一家披萨店构建一个应用程序,我们需要对他们的披萨类进行建模。假设他们提供四种类型的披萨,即活力派披萨、农舍披萨、玛格丽塔披萨和鸡肉嘉年华披萨。最初,我们只是使用继承并抽象出 披萨 上课。
每个披萨都有不同的价格。我们已经覆盖了子类中的getCost()以找到合适的成本。现在,假设有一个新的要求,除了一个披萨,顾客还可以要求几种配料,如新鲜番茄、烤盘、墨西哥胡椒、辣椒、烧烤、,等等。让我们思考一下,我们如何适应上述类别的变化,以便客户可以选择带配料的披萨,我们得到客户选择的披萨和配料的总成本。
让我们看看各种选择。
这看起来很复杂。有太多的类,是一个维护噩梦。此外,如果我们想添加新的配料或披萨,我们必须添加这么多的课程。这显然是非常糟糕的设计。
选项2: 让我们将实例变量添加到pizza基类中,以表示每个pizza是否都有顶部。类图如下所示:
超类的getCost()计算所有配料的成本,而子类中的一个加上特定披萨的成本。
// Sample getCost() in super class public int getCost() { int totalToppingsCost = 0; if (hasJalapeno() ) totalToppingsCost += jalapenoCost; if (hasCapsicum() ) totalToppingsCost += capsicumCost; // similarly for other toppings return totalToppingsCost; }
// Sample getCost() in subclass public int getCost() { // 100 for Margherita and super.getCost() // for toppings. return super.getCost() + 100; }
这个设计一开始看起来不错,但让我们看看与之相关的问题。
- 配料的价格变化将导致现行规范的变更。
- 新的toppings将迫使我们在超类中添加新方法并改变getCost()方法。
- 对于一些披萨,有些配料可能不合适,但子类继承了它们。
- 如果顾客想要双份辣椒或双份芝士汉堡呢?
简而言之,我们的设计违反了最流行的设计原则之一—— 开闭原理 声明类应该为扩展而打开,为修改而关闭。
在下一集中,我们将介绍Decorator模式,并将其应用于上述问题。
参考资料: 首当其冲的设计模式(书)。
本文由 苏拉布·库马尔 .如果你喜欢GeekSforgek,并且想贡献自己的力量,你也可以写一篇文章,并将文章邮寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。
如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写评论