现在进入下一个分类。
类型2:结构 - 装饰者设计模式
我将为您提供一个小场景,以便更好地说明为什么以及在何处使用装饰器模式。
假设你拥有一家咖啡店,像任何新手一样,你从两种普通咖啡开始,即家庭混合咖啡和深色烘焙咖啡。在您的计费系统中,有一个用于不同咖啡混合的类,该类继承了饮料抽象类。人们实际上开始过来喝你的美妙(尽管很苦?)咖啡。然后是咖啡新手,上帝保佑,他们想要糖或牛奶。咖啡真是太嘲讽了!!??
现在,您还需要将这两个附加组件也放在菜单上,不幸的是,在计费系统上。最初,您的IT人员将为两种咖啡制作一个子类,一种包括糖,另一种包括牛奶。然后,既然客户总是对的,人们会说这些可怕的话:
“我能喝点加糖的牛奶咖啡吗?”
???
你的计费系统再次在你的脸上笑了起来。好吧,回到绘图板.
然后,IT 人员将含糖的牛奶咖啡作为另一个子类添加到每个父咖啡类中。这个月剩下的时间一帆风顺,人们排队喝咖啡,你实际上赚钱了。??
但是,等等,还有更多!
世界再次与你作对。一个竞争对手在街对面打开,不仅有4种咖啡,还有10多种附加组件!
你买了所有这些甚至更多,自己卖更好的咖啡,然后记住你忘了更新那个沉闷的计费系统。您很可能无法为所有附加组件的任何和所有组合制作无限数量的子类,也可以使用新的咖啡混合物。更不用说最终系统的大小了。
是时候实际投资适当的计费系统了。你找到新的IT人员,他们实际上知道他们在做什么,他们说,
“为什么,如果它使用装饰器图案,这将变得容易得多,也更小。
那到底是什么?
装饰器设计模式属于结构类别,该类别处理类的实际结构,无论是通过继承,组合还是两者兼而有之。此设计的目标是在运行时修改对象的功能。这是许多其他设计模式之一,它们利用抽象类和具有组合的接口来获得所需的结果。
让我们给数学一个机会(不寒而栗?),把这一切带入视角。
取 4 种混合咖啡和 10 种附加组件。如果我们坚持为一种咖啡的所有附加组件的每个不同组合生成子类。那是:
(10–1)² = 9² = 81 个子类
我们从10中减去1,因为你不能将一个附加组件与另一个相同类型的附加组件组合在一起,糖与糖听起来很愚蠢。而这只适用于一种咖啡混合物。将81乘以4,你会得到一个惊人的324个不同的子类!谈论所有这些编码...
但是对于装饰器模式,在这种情况下,它只需要16个类。想下注吗?
装饰器设计模式类图
根据咖啡店场景的类图
如果我们根据上面的类图绘制我们的场景,我们将得到4个咖啡混合物的4个类,每个附加组件10个,抽象组件1个,抽象装饰器1个。看!260 亿现在交出那100美元.??(jk,但如果给予,它不会被拒绝...只是说)
从上面可以看出,正如具体的咖啡混合物是饮料抽象类的子类一样,AddOn抽象类也从它继承了它的方法。附加组件(即其子类)依次继承任何新方法,以便在需要时向基对象添加功能。
让我们开始编码,看看这个模式在使用中。
首先制作抽象饮料类,所有不同的咖啡混合物将继承自:
然后添加两个具体的咖啡混合类。
AddOn 抽象类也继承自饮料抽象类(下面将对此进行详细介绍)。
现在是这个抽象类的具体实现:
如您在上面看到的,我们可以将饮料的任何子类传递给AddOn的任何子类,并获得额外的成本以及更新的描述。而且,由于 AddOn 类本质上是饮料类型,我们可以将一个插件传递到另一个插件中。通过这种方式,我们可以将任意数量的附加组件添加到特定的咖啡混合物中。
现在编写一些代码来测试它。
最终结果是:
它的工作原理!我们能够向咖啡混合物添加多个附加组件,并成功更新其最终成本和描述,而无需为所有咖啡混合物的每个附加组合制作无限的子类。