-------装饰模式
装饰模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
-------1.介绍
意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
何时使用:在不想增加很多子类的情况下扩展类。
如何解决:将具体功能职责划分,同时继承装饰者模式。
关键代码: 1、Component 类充当抽象角色,不应该具体实现。 2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。
应用实例: 1、孙悟空有 72 变,当他变成"庙宇"后,他的根本还是一只猴子,但是他又有了庙宇的功能。 2、不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂。
使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。
注意事项:可代替继承。
-------2.实例
2.1把一个形状装饰上不同的颜色,同时又不改变形状类
2.1.1.我们将创建一个 Shape 接口和实现了 Shape 接口的实体类。然后我们创建一个实现了 Shape 接口的抽象装饰类 ShapeDecorator,并把 Shape 对象作为它的实例变量。
2.1.2.RedShapeDecorator 是实现了 ShapeDecorator 的实体类。
2.1.3.test,我们的演示类使用 RedShapeDecorator 来装饰 Shape 对象。
1 packagedecorate;2
3 /**
4 *@authorAdministrator5 * 形状接口6 */
7 public interfaceShape {8 voiddraw();9 }10
11
12
13 packagedecorate;14
15 /**
16 *@authorAdministrator17 *长方形18 */
19 public class Rectangle implementsShape {20
21 @Override22 public voiddraw() {23 //TODO Auto-generated method stub
24 System.out.println("形状:长方形");25 }26
27
28 }29
30
31
32
33
34 packagedecorate;35
36 /**
37 *@authorAdministrator38 *圆形39 */
40 public class Circle implementsShape {41
42 @Override43 public voiddraw() {44 //TODO Auto-generated method stub
45 System.out.println("形状:圆形");46 }47
48
49 }50
51
52
53
54 packagedecorate;55
56 /**
57 *@authorAdministrator58 * 装饰对象59 */
60 public abstract class ShapeDecorator implements Shape {//装饰器
61 protectedShape decoratedShape;62 @Override63 public voiddraw() {64 //TODO Auto-generated method stub
65 decoratedShape.draw();66 }67 publicShapeDecorator(Shape decoratedShape) {68 this.decoratedShape =decoratedShape;69 }70
71
72 }
1 packagedecorate;2
3 /**
4 *@authorAdministrator5 * 颜色 红色6 */
7 public class RedShapeDecorator extendsShapeDecorator {8
9 publicRedShapeDecorator(Shape decoratedShape) {10 super(decoratedShape);11 //TODO Auto-generated constructor stub
12 }13
14 @Override15 public voiddraw() {16 //TODO Auto-generated method stub
17 decoratedShape.draw();18 setRedBorder(decoratedShape);19 }20
21 public voidsetRedBorder(Shape decoratedShape){22 System.out.println("颜色: Red");23 }24
25 }
1 packagedecorate;2
3 public classTest {4 public static voidmain(String[] args) {5 Shape shape=newCircle();6 Shape redCircle=new RedShapeDecorator(newCircle());7 shape.draw();8 System.out.println();9 redCircle.draw();10 }11 }
输出结果:
形状:圆形
形状:圆形
颜色: Red
2.2.装饰模式为已有类动态附加额外的功能就像LOL英雄升级一样。每次英雄升级都会附加一个额外技能点学习技能。
1 packagelol;2
3 /**
4 *@authorGH5 * 英雄接口6 */
7 public interfaceHero {8 voidstudy();9 }10
11
12
13 packagelol;14
15 /**
16 *@authorGH17 * 具体的英雄 蛮王18 */
19 public class BarbarianKing implementsHero {20 privateString name;21 @Override22 public voidstudy() {23 //TODO Auto-generated method stub
24 System.out.println("英雄:"+name);25 }26 publicBarbarianKing(String name) {27 super();28 this.name =name;29 }30
31 }32
33
34
35 packagelol;36
37 /**
38 *@authorAdministrator39 * 技能装饰器40 */
41 public abstract class Skills implementsHero{42 protectedHero heroSkill;43
44 publicSkills(Hero heroSkill) {45 this.heroSkill =heroSkill;46 }47 @Override48 public voidstudy() {49 //TODO Auto-generated method stub
50 heroSkill.study();51 }52 }53
54
55
56 packagelol;57
58 /**
59 *@authorAdministrator60 *具体技能Q61 */
62 public class KillQ extendsSkills {63
64 publicKillQ(Hero heroSkill) {65 super(heroSkill);66 //TODO Auto-generated constructor stub
67 }68
69 @Override70 public voidstudy() {71 //TODO Auto-generated method stub
72 heroSkill.study();73 setkill(heroSkill);74 }75 public voidsetkill(Hero hero){76 System.out.println("习得技能:Q");77 }78
79 }80
81
82
83 packagelol;84
85 /**
86 *@authorAdministrator87 *具体技能W88 */
89 public class KillW extendsSkills {90
91 publicKillW(Hero heroSkill) {92 super(heroSkill);93 //TODO Auto-generated constructor stub
94 }95
96 @Override97 public voidstudy() {98 //TODO Auto-generated method stub
99 heroSkill.study();100 setkill(heroSkill);101 }102 public voidsetkill(Hero hero){103 System.out.println("习得技能:W");104 }105
106 }107
108
109 packagelol;110
111 public classTest {112
113 public static voidmain(String[] args) {114 //TODO Auto-generated method stub
115 Hero hero=new BarbarianKing("蛮王");116 hero.study();117 System.out.println();118 KillQ q=newKillQ(hero);119 q.study();120
121 System.out.println();122 KillQ q2=newKillQ(q);123 q2.study();124
125 System.out.println();126 KillW w=newKillW(q2);127 w.study();128 }129
130 }
输出结果:
英雄:蛮王
英雄:蛮王
习得技能:Q
英雄:蛮王
习得技能:Q
习得技能:Q
英雄:蛮王
习得技能:Q
习得技能:Q
习得技能:W
-------3.总结:
装饰模式是为已有功能动态的添加更多功能的一种方式。当系统需要新功能的时候,通过新加代码来装饰原有类的核心职责,而这些新加的东西仅仅是为了满足一些只在特殊情况下才会执行的特殊行为。装饰模式的有点其实就是:把类中装饰功能从类中搬除出去,在简化原有类的基础上有效的把类的核心职责和装饰功能区分开来。