小职
2018-06-21
来源 :
阅读 1527
评论 0
摘要:JAVA语言是装饰者模式,定义:动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。希望对大家学习JAVA语言有所帮助。
JAVA语言是装饰者模式,定义:动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。希望对大家学习JAVA语言有所帮助。
设计初衷:通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的。
要点: 装饰者与被装饰者拥有共同的超类,继承的目的是继承类型,而不是行为
实际上Java 的I/O API就是使用Decorator实现的。
[java] view plain copy
1. //定义被装饰者
2. public interface Human {
3. public void wearClothes();
4.
5. public void walkToWhere();
6. }
7.
8. //定义装饰者
9. public abstract class Decorator implements Human {
10. private Human human;
11.
12. public Decorator(Human human) {
13. this.human = human;
14. }
15.
16. public void wearClothes() {
17. human.wearClothes();
18. }
19.
20. public void walkToWhere() {
21. human.walkToWhere();
22. }
23. }
24.
25. //下面定义三种装饰,这是第一个,第二个第三个功能依次细化,即装饰者的功能越来越多
26. public class Decorator_zero extends Decorator {
27.
28. public Decorator_zero(Human human) {
29. super(human);
30. }
31.
32. public void goHome() {
33. System.out.println("进房子。。");
34. }
35.
36. public void findMap() {
37. System.out.println("书房找找Map。。");
38. }
39.
40. @Override
41. public void wearClothes() {
42. // TODO Auto-generated method stub
43. super.wearClothes();
44. goHome();
45. }
46.
47. @Override
48. public void walkToWhere() {
49. // TODO Auto-generated method stub
50. super.walkToWhere();
51. findMap();
52. }
53. }
54.
55. public class Decorator_first extends Decorator {
56.
57. public Decorator_first(Human human) {
58. super(human);
59. }
60.
61. public void goClothespress() {
62. System.out.println("去衣柜找找看。。");
63. }
64.
65. public void findPlaceOnMap() {
66. System.out.println("在Map上找找。。");
67. }
68.
69. @Override
70. public void wearClothes() {
71. // TODO Auto-generated method stub
72. super.wearClothes();
73. goClothespress();
74. }
75.
76. @Override
77. public void walkToWhere() {
78. // TODO Auto-generated method stub
79. super.walkToWhere();
80. findPlaceOnMap();
81. }
82. }
83.
84. public class Decorator_two extends Decorator {
85.
86. public Decorator_two(Human human) {
87. super(human);
88. }
89.
90. public void findClothes() {
91. System.out.println("找到一件D&G。。");
92. }
93.
94. public void findTheTarget() {
95. System.out.println("在Map上找到神秘花园和城堡。。");
96. }
97.
98. @Override
99. public void wearClothes() {
100. // TODO Auto-generated method stub
101. super.wearClothes();
102. findClothes();
103. }
104.
105. @Override
106. public void walkToWhere() {
107. // TODO Auto-generated method stub
108. super.walkToWhere();
109. findTheTarget();
110. }
111. }
112.
113. //定义被装饰者,被装饰者初始状态有些自己的装饰
114. public class Person implements Human {
115.
116. @Override
117. public void wearClothes() {
118. // TODO Auto-generated method stub
119. System.out.println("穿什么呢。。");
120. }
121.
122. @Override
123. public void walkToWhere() {
124. // TODO Auto-generated method stub
125. System.out.println("去哪里呢。。");
126. }
127. }
128. //测试类,看一下你就会发现,跟java的I/O操作有多么相似
129. public class Test {
130. public static void main(String[] args) {
131. Human person = new Person();
132. Decorator decorator = new Decorator_two(new Decorator_first(
133. new Decorator_zero(person)));
134. decorator.wearClothes();
135. decorator.walkToWhere();
136. }
137. }运行结果:

其实就是进房子找衣服,然后找地图这样一个过程,通过装饰者的三层装饰,把细节变得丰富。
关键点:
1、Decorator抽象类中,持有Human接口,方法全部委托给该接口调用,目的是交给该接口的实现类即子类进行调用。
2、Decorator抽象类的子类(具体装饰者),里面都有一个构造方法调用super(human),这一句就体现了抽象类依赖于子类实现即抽象依赖于实现的原则。因为构造里面参数都是Human接口,只要是该Human的实现类都可以传递进去,即表现出Decorator dt = new Decorator_second(new Decorator_first(new Decorator_zero(human)));这种结构的样子。所以当调用dt.wearClothes();dt.walkToWhere()的时候,又因为每个具体装饰者类中,都先调用super.wearClothes和super.walkToWhere()方法,而该super已经由构造传递并指向了具体的某一个装饰者类(这个可以根据需要调换顺序),那么调用的即为装饰类的方法,然后才调用自身的装饰方法,即表现出一种装饰、链式的类似于过滤的行为。
3、具体被装饰者类,可以定义初始的状态或者初始的自己的装饰,后面的装饰行为都在此基础上一步一步进行点缀、装饰。
4、装饰者模式的设计原则为:对扩展开放、对修改关闭,这句话体现在我如果想扩展被装饰者类的行为,无须修改装饰者抽象类,只需继承装饰者抽象类,实现额外的一些装饰或者叫行为即可对被装饰者进行包装。所以:扩展体现在继承、修改体现在子类中,而不是具体的抽象类,这充分体现了依赖倒置原则,这是自己理解的装饰者模式。
说的不清楚,有些只可意会不可言传的感觉,多看几遍代码,然后自己敲出来运行一下,基本上就领悟了。
下面这个例子也有助于理解 装饰的流程和作用
现在需要一个汉堡,主体是鸡腿堡,可以选择添加生菜、酱、辣椒等等许多其他的配料,这种情况下就可以使用装饰者模式。
汉堡基类(被装饰者,相当于上面的Human)
[java] view plain copy
1. package decorator;
2.
3. public abstract class Humburger {
4.
5. protected String name ;
6.
7. public String getName(){
8. return name;
9. }
10.
11. public abstract double getPrice();
12.
13. }
鸡腿堡类(被装饰者的初始状态,有些自己的简单装饰,相当于上面的Person)
[java] view plain copy
1. package decorator;
2.
3. public class ChickenBurger extends Humburger {
4.
5. public ChickenBurger(){
6. name = "鸡腿堡";
7. }
8.
9. @Override
10. public double getPrice() {
11. return 10;
12. }
13.
14. }配料的基类(装饰者,用来对汉堡进行多层装饰,每层装饰增加一些配料,相当于上面Decorator)
[java] view plain copy
1. package decorator;
2.
3. public abstract class Condiment extends Humburger {
4.
5. public abstract String getName();
6.
7. }
生菜(装饰者的第一层,相当于上面的decorator_zero)
[java] view plain copy
1. package decorator;
2.
3. public class Lettuce extends Condiment {
4.
5. Humburger humburger;
6.
7. public Lettuce(Humburger humburger){
8. this.humburger = humburger;
9. }
10.
11. @Override
12. public String getName() {
13. return humburger.getName()+" 加生菜";
14. }
15.
16. @Override
17. public double getPrice() {
18. return humburger.getPrice()+1.5;
19. }
20.
21. }
辣椒(装饰者的第二层,相当于上面的decorator_first)
[java] view plain copy
1. package decorator;
2.
3. public class Chilli extends Condiment {
4.
5. Humburger humburger;
6.
7. public Chilli(Humburger humburger){
8. this.humburger = humburger;
9.
10. }
11.
12. @Override
13. public String getName() {
14. return humburger.getName()+" 加辣椒";
15. }
16.
17. @Override
18. public double getPrice() {
19. return humburger.getPrice(); //辣椒是免费的哦
20. }
21.
22. }
测试类
[java] view plain copy
1. package decorator;
2.
3. public class Test {
4.
5. /**
6. * @param args
7. */
8. public static void main(String[] args) {
9. Humburger humburger = new ChickenBurger();
10. System.out.println(humburger.getName()+" 价钱:"+humburger.getPrice());
11. Lettuce lettuce = new Lettuce(humburger);
12. System.out.println(lettuce.getName()+" 价钱:"+lettuce.getPrice());
13. Chilli chilli = new Chilli(humburger);
14. System.out.println(chilli.getName()+" 价钱:"+chilli.getPrice());
15. Chilli chilli2 = new Chilli(lettuce);
16. System.out.println(chilli2.getName()+" 价钱:"+chilli2.getPrice());
17. }
18.
19. }
输出
[java] view plain copy
1. 鸡腿堡 价钱:10.0
2. 鸡腿堡 加生菜 价钱:11.5
3. 鸡腿堡 加辣椒 价钱:10.0
4. 鸡腿堡 加生菜 加辣椒 价钱:11.5本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注编程语言JAVA频道!
喜欢 | 2
不喜欢 | 0
您输入的评论内容中包含违禁敏感词
我知道了

请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号