装饰模式
一 场景
在软件开发中,我们有时候需要对一个已经存在对象的某个功能进行扩展。如果我们在这个对象的功能基础上进行修改,比如加入了新的字段,新的方法。这样就会增加原有对象的复杂度,不符合开闭原则。
有没有什么方法能既可以不改变原对象,又可以对对象的功能进行扩展了?装饰模式恰好针对这种情况提供了一个非常好的解决方案,它把要装饰的功能单独的封装在一个新的装饰类中,再让这个装饰类包装它所要装饰的原对象。在装饰类中既可以调用原对象的方法,还可以增加新的方法,以扩充原对象的功能。这样装饰模式就有效地把类的原核心功能和新增的装饰功能区分开,并去除了相关类中重复的装饰逻辑,符合了开闭原则。
二 定义
装饰模式动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式提供了比继承实现更为灵活的替代方案。
三 类图
Component(抽象构件类):抽象构件类一般被定义为一个接口或者是一个抽象类。具体构件类和抽象装饰类都是它的子类。在抽象构建类中定义了一些业务方法,具体构件类负责对这些业务方法给出具体的实现。
抽象构件类的引入,可以使客户端以一致的方式处理具体的构件对象和具体装饰对象。
ConcreteComponent(具体构件类):具体构件类是抽象构件类的子类,它实现了在抽象构件类中声明的业务方法,在装饰模式中就是对具体构件类中的业务方法给予增强,增加了额外的职责。
Decorator(抽象装饰类):抽象装饰类是具体装饰类的父类,它同时也是抽象构建类的子类。
在抽象装饰类主要是声明了用于给具体构件对象增加的职责,这些增加的具体职责是在具体装饰类中给予实现的。
在抽象装饰类中维护了一个对抽象构件对象的引用,通过这个引用可以调用未装饰的具体构件对象中的业务方法。
ConcreteDecorator(具体装饰类):具体装饰类是抽象装饰类的子类,负责向具体构件类中添加新的职责。
每一个具体装饰类都实现了一些新的用于增强行为的方法。它可以调用在抽象装饰类中定义的业务方法时候,可以增加这些新的方法,来扩充和增强原具体构件对象的业务方法,从而达到装饰的目的。
四 代码示例
我们平时会过很多节日,传统的节日有春节,洋节的话有圣诞节。过节的话,我们一般都会进行一些庆祝的活动。在节日中为了烘托气氛,我们会对家里进行一些装饰活动。以春节为例的话,我们一般会大门上贴春联,在屋檐下挂红灯笼,来装饰我们的房子,以此来烘托节日的气氛。针对以上情景,我可以使用装饰模式来进行设计。
我们定义一个IHoliday接口(抽象构件类)来表示抽象的节日,在接口中定义了一个庆祝的方法。
节日有很多种,我们可以以春节(具体构件类)为例,定义一个SpringFestival类。SpringFestival类继承了IHoliday接口,实现了celebrate()方法。
我们定义了一个抽象的节日装饰类AbstractHolidayDecorator(抽象装饰类),该类也实现了IHoliday接口,并在该类中维持了一个IHoliday实例的引用。IHoliday实例的引用是通过在构造函数中来赋值。
挂红灯笼是对节日的一种装饰,我们定义了HangRedLanternDecorator类(具体装饰类)。它继承了AbstractHolidayDecorator类,覆写了celebrate()方法。在原celebrate()方法中,增加挂红灯笼这个功能doHangRedLantern()。对原celebrate()方法进行了增强。
同理贴春联的子类也是一样
运行示例
运行结果
五 总结
装饰模式是一种对象结构型模式。它是为已有的功能动态地进行增强的一种方式。装饰模式是一种用于替代继承的技术,它通过一种无须定义子类的方式来给对象动态增加职责,使用对象之间的关联关系来取代类之间的继承关系。
优点:
- 装饰模式可以动态的增强一个对象的功能,且比继承更加具有灵活性。装饰模式无需定义子类,不会导致类的个数急剧增加。
- 装饰模式把的装饰功能代码从原类中搬移去除,这样简化了原有的类。装饰模式有效地把类中的原有核心职责和新增的装饰功能区分开,使得系统易于维护。
- 装饰模式可以对一个对象进行多次装饰,我们可以根据需要有选择地、按顺序地使用装饰功能来多次包装对象,从而得到一个功能更为强大的对象。
缺点:
- 装饰模式中对于原对象每一种增加的功能,我们都需要对应的定义一个具体的装饰类。这样就会导致系统出现比较多的小类。
标签:对象,模式,抽象,构件,具体,装饰,类中 From: https://www.cnblogs.com/YaoxTao/p/17074042.html