定义
在不改变原有对象的基础之上,将功能附加到对象上; 提供了比继承更有弹性的替代方案(扩展原有对象功能)
适用场景
扩展一个类的功能或给一个类添加附加职责
动态的给一个对象添加功能,这些功能可以再动态的撤销
优点和缺点 优点
继承的有力补充,比继承灵活,不改变原有对象的情况下给一个对象扩展功能;
通过使用不同装饰类以及这些装饰类的排列组合,可以试想不同效果;
符合开闭原则。
缺点
会出现更多的代码,更多的类,增加程序复杂性;
动态装饰时,多层装饰时会更复杂。
结构
抽象构件角色: 定义一个抽象接口以规范准备接收附加责任的对象。
具体构件角色: 实现抽象构件,通过装饰角色为其添加一些职责。
抽象装饰角色: 继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
具体装饰角色: 实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
代码实现 假设我们去买煎饼,一个煎饼8元钱,可以加鸡蛋和香肠,以传统方式来实现,如果用户只是买一个煎饼,我们建一个煎饼类即可实现,如果用户想要加一个鸡蛋,可以新建一个类继承煎饼类来实现,但是如果用户想再加香肠呢?再鸡蛋呢?两个、三个… 很明显,如果再以简单的继承来去实现,我们的类会爆炸式的增加,所以我们可以引入装饰者模式,把鸡蛋和香肠作为装饰,可以动态添加。
首先创建一个抽象构件角色:(煎饼以及作为装饰的抽象类)
1 2 3 4 public abstract class APancakes { abstract String getDesc () ; abstract int cost () ; }
具体构件角色:(具体煎饼类,可以有多种煎饼)
1 2 3 4 5 6 7 8 9 10 11 public class Pancakes extends APancakes { @Override String getDesc () { return "煎饼" ; } @Override int cost () { return 8 ; } }
抽象装饰角色:(具体装饰角色的抽象类,也可以使用对象类,具体根据业务情况决定)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class AbstractDecorator extends APancakes { private APancakes aPancakes; public AbstractDecorator (APancakes aPancakes) { this .aPancakes = aPancakes; } @Override String getDesc () { return aPancakes.getDesc(); } @Override int cost () { return aPancakes.cost(); } }
具体装饰角色:(装饰角色的具体实现) 鸡蛋实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class EggDecorator extends AbstractDecorator { public EggDecorator (APancakes aPancakes) { super (aPancakes); } @Override String getDesc () { return super .getDesc() + " 加一个鸡蛋" ; } @Override int cost () { return super .cost() + 1 ; } }
香肠实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class SausageDecorator extends AbstractDecorator { public SausageDecorator (APancakes aPancakes) { super (aPancakes); } @Override String getDesc () { return super .getDesc() + " 加一根香肠" ; } @Override int cost () { return super .cost() + 2 ; } }
具体调用:
1 2 3 4 5 6 7 8 9 10 public class Test { public static void main (String[] args) { APancakes aPancakes = new Pancakes(); aPancakes = new EggDecorator(aPancakes); aPancakes = new EggDecorator(aPancakes); aPancakes = new SausageDecorator(aPancakes); System.out.println(aPancakes.getDesc()+aPancakes.cost()); } }
如代码所示,想要加几个鸡蛋或者香肠,可以动态的去实现
结果:
UML类图