装饰模式【Decorator Pattern 】
2016-01-11 10:29
309 查看
博客地址 http://blog.csdn.net/ftx2540993425
下面横线以上内容是借鉴别人的,为了表达对作者的敬意,不做不恰当的修改,我个人的总结在后面。好的东西
Ladies and gentlemen,May I get your attention,Please?,Now I’m going to talk about decoratorpattern.装饰模式在中国使用的那实在是多,中国的文化是中庸文化,说话或做事情都不能太直接,需要
有技巧的,比如说话吧,你要批评一个人,你不能一上来就说你这个做的不对,那个做的不对,你要先肯
定他的成绩,表扬一下优点,然后再指出瑕疵,指出错误的地方,最后再来个激励,你修改了这些缺点后
有那些好处,比如你能带更多的小兵,到个小头目等等,否则你一上来就是一顿批评,你瞅瞅看,肯定是
不服气,顶撞甚至是直接“此处不养爷,自有养爷处”开溜哇。这是说话,那做事情也有很多,在山寨产
品流行之前,假货很是比较盛行的,我在 2002 年买了个手机,当时老板吹的是天花乱坠,承诺这个手机是
最新的,我看着也像,壳子是崭新的,包装是崭新的,没有任何瑕疵,就是比正品便宜了一大截,然后我
买了,缺钱哪,用来 3 个月,坏了,一送修,检查,说这是个新壳装旧机,我晕!拿一个旧手机的线路板,
找个新的外壳、屏幕、包装就成了新手机,装饰模式害人不浅呀!
我们不说不开心的事情,今天举一个什么例子呢?就说说我上小学的的糗事吧。我上小学的时候学习
成绩非常的差,班级上 40 多个同学,我基本上都是在排名 45 名以后,按照老师给我的定义就是“不是读
书的料” ,但是我老爸管的很严格,明知道我不是这块料,还是往赶鸭子上架,每次考试完毕我都是战战兢
兢的, “竹笋炒肉”是肯定少不了的,能少点就少点吧,肉可是自己的呀。四年级期末考试考完,学校出来
个很损的招儿(这招儿现在很流行的) ,打印出成绩单,要家长签字,然后才能上五年级,我那个恐惧呀,
不过也就是几秒钟的时间,玩起来什么都忘记了。
我们先看看这个成绩单的类图:
成绩单的抽象类,然后有一个四年级的成绩单实现类,先看抽象类:
爱学习的人太多了!怎么着,那我把这个成绩单给老爸看看?好,我们修改一下类图,成绩单给老爸看:
老爸开始看成绩单,这个成绩单可是最真实的,啥都没有动过,原装,看 Father 类:
尊敬的XXX家长:
......
语文 62 数学65 体育 98 自然 63
.......
家长签名:
就这成绩还要我签字?!老爸就开始找笤帚,我的屁股已经做好了准备,肌肉要绷紧,要不那个太疼了!哈
哈,幸运的是,这个不是当时的真实情况,我没有直接把成绩单交给老爸,而是在交给他之前做了点技术工作,
我要把成绩单封装一下,封装分类两步走:
第一步:跟老爸说各个科目的最高分,语文最高是 75,数学是 78,自然是 80,然老爸觉的我成绩与最高分
数相差不多,这个是实情,但是不知道是什么原因,反正期末考试都考的不怎么样,但是基本上都集中在 70 分
以上,我这 60 多分基本上还是垫底的角色;
第二步:在老爸看成绩单后,告诉他我是排名第 38 名,全班,这个也是实情,为啥呢?有将近十个同学退
学了!这个情况我是不说的。不知道是不是当时第一次发成绩单,学校没有考虑清楚,没有写上总共有多少同学,
排名第几名等等,反正是被我钻了个空子。
那修饰是说完了,我们看看类图如何修改:
我想这是你最容易想到的类图,通过直接增加了一个子类,重写 report 方法,很容易的解决了这个问题,
是不是这样?是的,确实是,确实是一个很好的办法,我们来看具体的实现:
这次考试语文最高是75,数学是78,自然是80
尊敬的XXX家长:
......
语文 62 数学65 体育 98 自然 63
.......
家长签名:
我是排名第38名...
家长签名为:老三
通过继承确实能够解决这个问题,老爸看成绩单很开心,然后就给签字了,但是现实的情况很复杂的,可能
老爸听我汇报最高成绩后,就直接乐开花了,直接签名了,后面的排名就没必要了,或者老爸要先听排名情况,
那怎么办?继续扩展类?你能扩展多少个类?这还是一个比较简单的场景,一旦需要装饰的条件非常的多,比如
20 个,你还通过继承来解决,你想想的子类有多少个?你是不是马上就要崩溃了!
好,你也看到通过继承情况确实出现了问题,类爆炸,类的数量激增,光写这些类不累死你才怪,而且还要
想想以后维护怎么办,谁愿意接收这么一大堆类的维护哪?并且在面向对象的设计中,如果超过 2 层继承,你就
应该想想是不是出设计问题了,是不是应该重新找一条道了,这是经验值,不是什么绝对的,继承层次越多你以
后的维护成本越多,问题这么多,那怎么办?好办,装饰模式出场来解决这些问题,我们先来看类图:
增加一个抽象类和两个实现类,其中 Decorator 的作用是封装 SchoolReport 类,看源代码:
report 方法!先看 HighScoreDecorator 实现类:
我们再来看怎么回报学校排序情况 SortDecorator 代码:
躲过了一顿海扁。
下面横线以上内容是借鉴别人的,为了表达对作者的敬意,不做不恰当的修改,我个人的总结在后面。好的东西
Ladies and gentlemen,May I get your attention,Please?,Now I’m going to talk about decoratorpattern.装饰模式在中国使用的那实在是多,中国的文化是中庸文化,说话或做事情都不能太直接,需要
有技巧的,比如说话吧,你要批评一个人,你不能一上来就说你这个做的不对,那个做的不对,你要先肯
定他的成绩,表扬一下优点,然后再指出瑕疵,指出错误的地方,最后再来个激励,你修改了这些缺点后
有那些好处,比如你能带更多的小兵,到个小头目等等,否则你一上来就是一顿批评,你瞅瞅看,肯定是
不服气,顶撞甚至是直接“此处不养爷,自有养爷处”开溜哇。这是说话,那做事情也有很多,在山寨产
品流行之前,假货很是比较盛行的,我在 2002 年买了个手机,当时老板吹的是天花乱坠,承诺这个手机是
最新的,我看着也像,壳子是崭新的,包装是崭新的,没有任何瑕疵,就是比正品便宜了一大截,然后我
买了,缺钱哪,用来 3 个月,坏了,一送修,检查,说这是个新壳装旧机,我晕!拿一个旧手机的线路板,
找个新的外壳、屏幕、包装就成了新手机,装饰模式害人不浅呀!
我们不说不开心的事情,今天举一个什么例子呢?就说说我上小学的的糗事吧。我上小学的时候学习
成绩非常的差,班级上 40 多个同学,我基本上都是在排名 45 名以后,按照老师给我的定义就是“不是读
书的料” ,但是我老爸管的很严格,明知道我不是这块料,还是往赶鸭子上架,每次考试完毕我都是战战兢
兢的, “竹笋炒肉”是肯定少不了的,能少点就少点吧,肉可是自己的呀。四年级期末考试考完,学校出来
个很损的招儿(这招儿现在很流行的) ,打印出成绩单,要家长签字,然后才能上五年级,我那个恐惧呀,
不过也就是几秒钟的时间,玩起来什么都忘记了。
我们先看看这个成绩单的类图:
成绩单的抽象类,然后有一个四年级的成绩单实现类,先看抽象类:
package com.cbf4life; /** * @author cbf4Life cbf4life@126.com * I'm glad to share my knowledge with you all. * 成绩单的抽象类 */ public abstract class SchoolReport { //成绩单的主要展示的就是你的成绩情况 public abstract void report(); //成绩单要家长签字,这个是最要命的 public abstract void sign(); }然后看我们的实现类 FouthGradSchoolReport:
package com.cbf4life; /** * @author cbf4Life cbf4life@126.com * I'm glad to share my knowledge with you all. * 四年级的成绩单,这个是我们学校第一次实施,以前没有干过 * 这种“缺德”事。 */ public class FouthGradeSchoolReport extends SchoolReport { //我的成绩单 public void report() { //成绩单的格式是这个样子的 System.out.println("尊敬的XXX家长:"); System.out.println(" ......"); System.out.println(" 语文 62 数学65 体育 98 自然 63"); System.out.println(" ......."); System.out.println(" 家长签名: "); } //家长签名 public void sign(String name) { System.out.println("家长签名为:"+name); } }成绩单出来,你别看什么 62,65 之类的成绩,你要知道在小学低于 90 分基本上就是中下等了,唉,
爱学习的人太多了!怎么着,那我把这个成绩单给老爸看看?好,我们修改一下类图,成绩单给老爸看:
老爸开始看成绩单,这个成绩单可是最真实的,啥都没有动过,原装,看 Father 类:
package com.cbf4life; /** * @author cbf4Life cbf4life@126.com * I'm glad to share my knowledge with you all. * 老爸看成绩单了 */ public class Father { public static void main(String[] args) { //成绩单拿过来 SchoolReport sr = new FouthGradeSchoolReport(); //看成绩单 sr.report(); //签名?休想! } }运行结果如下:
尊敬的XXX家长:
......
语文 62 数学65 体育 98 自然 63
.......
家长签名:
就这成绩还要我签字?!老爸就开始找笤帚,我的屁股已经做好了准备,肌肉要绷紧,要不那个太疼了!哈
哈,幸运的是,这个不是当时的真实情况,我没有直接把成绩单交给老爸,而是在交给他之前做了点技术工作,
我要把成绩单封装一下,封装分类两步走:
第一步:跟老爸说各个科目的最高分,语文最高是 75,数学是 78,自然是 80,然老爸觉的我成绩与最高分
数相差不多,这个是实情,但是不知道是什么原因,反正期末考试都考的不怎么样,但是基本上都集中在 70 分
以上,我这 60 多分基本上还是垫底的角色;
第二步:在老爸看成绩单后,告诉他我是排名第 38 名,全班,这个也是实情,为啥呢?有将近十个同学退
学了!这个情况我是不说的。不知道是不是当时第一次发成绩单,学校没有考虑清楚,没有写上总共有多少同学,
排名第几名等等,反正是被我钻了个空子。
那修饰是说完了,我们看看类图如何修改:
我想这是你最容易想到的类图,通过直接增加了一个子类,重写 report 方法,很容易的解决了这个问题,
是不是这样?是的,确实是,确实是一个很好的办法,我们来看具体的实现:
package com.cbf4life; /** * @author cbf4Life cbf4life@126.com * I'm glad to share my knowledge with you all. * 对这个成绩单进行美化 * Sugar这个词太好了,名词是糖的意思,动词就是美化 * 给你颗糖你还不美去 */ public class SugarFouthGradeSchoolReport extends FouthGradeSchoolReport { //首先要定义你要美化的方法,先给老爸说学校最高成绩 private void reportHighScore(){ System.out.println("这次考试语文最高是75,数学是78,自然是80"); } //在老爸看完毕成绩单后,我再汇报学校的排名情况 private void reportSort(){ System.out.println("我是排名第38名..."); } //由于汇报的内容已经发生变更,那所以要重写父类 @Override this.reportHighScore(); //先说最高成绩 super.report(); //然后老爸看成绩单 this.reportSort(); //然后告诉老爸学习学校排名 } } public void report(){ this.reportHighScore(); //先说最高成绩 super.report(); //然后老爸看成绩单 this.reportSort(); //然后告诉老爸学习学校排名 } }然后 Father 类稍做修改就可以看到美化后的成绩单,看代码如下:
package com.cbf4life; /** * @author cbf4Life cbf4life@126.com * I'm glad to share my knowledge with you all. * 老爸看成绩单了 */ public class Father { public static void main(String[] args) { //美化过的成绩单拿过来 SchoolReport sr= new SugarFouthGradeSchoolReport(); //看成绩单 sr.report(); //然后老爸,一看,很开心,就签名了 sr.sign("老三"); //我叫小三,老爸当然叫老三 } }运行结果如下:
这次考试语文最高是75,数学是78,自然是80
尊敬的XXX家长:
......
语文 62 数学65 体育 98 自然 63
.......
家长签名:
我是排名第38名...
家长签名为:老三
通过继承确实能够解决这个问题,老爸看成绩单很开心,然后就给签字了,但是现实的情况很复杂的,可能
老爸听我汇报最高成绩后,就直接乐开花了,直接签名了,后面的排名就没必要了,或者老爸要先听排名情况,
那怎么办?继续扩展类?你能扩展多少个类?这还是一个比较简单的场景,一旦需要装饰的条件非常的多,比如
20 个,你还通过继承来解决,你想想的子类有多少个?你是不是马上就要崩溃了!
好,你也看到通过继承情况确实出现了问题,类爆炸,类的数量激增,光写这些类不累死你才怪,而且还要
想想以后维护怎么办,谁愿意接收这么一大堆类的维护哪?并且在面向对象的设计中,如果超过 2 层继承,你就
应该想想是不是出设计问题了,是不是应该重新找一条道了,这是经验值,不是什么绝对的,继承层次越多你以
后的维护成本越多,问题这么多,那怎么办?好办,装饰模式出场来解决这些问题,我们先来看类图:
增加一个抽象类和两个实现类,其中 Decorator 的作用是封装 SchoolReport 类,看源代码:
package com.cbf4life; /** * @author cbf4Life cbf4life@126.com * I'm glad to share my knowledge with you all. * 装饰类,我要把我的成绩单装饰一下 */ public abstract class Decorator extends SchoolReport{ //首先我要知道是那个成绩单 private SchoolReport sr; //构造函数,传递成绩单过来 public Decorator(SchoolReport sr){ this.sr = sr; } //成绩单还是要被看到的 public void report(){ this.sr.report(); } //看完毕还是要签名的 public void sign(String name){ this.sr.sign(name); } }Decorator 抽象类的目的很简单,就是要让子类来对封装 SchoolReport 的子类,怎么封装?重写
report 方法!先看 HighScoreDecorator 实现类:
package com.cbf4life; /** * @author cbf4Life cbf4life@126.com * I'm glad to share my knowledge with you all. * 我要把我学校的最高成绩告诉老爸 */ public class HighScoreDecorator extends Decorator { //构造函数 public HighScoreDecorator(SchoolReport sr){ super(sr); } //我要汇报最高成绩 private void reportHighScore(){ System.out.println("这次考试语文最高是75,数学是78,自然是80"); } //最高成绩我要做老爸看成绩单前告诉他,否则等他一看,就抡起笤帚有揍我,我那还有机会说呀 @Override public void report(){ this.reportHighScore(); super.report(); } }重写了 report 方法,先调用具体装饰类的装饰方法 reportHighScore,然后再调用具体构件的方法,
我们再来看怎么回报学校排序情况 SortDecorator 代码:
package com.cbf4life; /** * @author cbf4Life cbf4life@126.com * I'm glad to share my knowledge with you all. * 学校排名的情况汇报 */ public class SortDecorator extends Decorator { //构造函数 public SortDecorator(SchoolReport sr){ super(sr); } //告诉老爸学校的排名情况 private void reportSort(){ System.out.println("我是排名第38名..."); } //老爸看完成绩单后再告诉他,加强作用 @Override public void report(){ super.report(); this.reportSort(); } }然后看看我老爸怎么看成绩单的:
package com.cbf4life; /** * @author cbf4Life cbf4life@126.com * I'm glad to share my knowledge with you all. * 老爸看成绩单了 */ public class Father { public static void main(String[] args) { //成绩单拿过来 SchoolReport sr; sr = new FouthGradeSchoolReport(); //原装的成绩单 //加 了最高分说明的成绩单 sr = new HighScoreDecorator(sr); //又加了成绩排名的说明 sr = new SortDecorator(sr); //看成绩单 sr.report(); //然后老爸,一看,很开心,就签名了 sr.sign("老三"); //我叫小三,老爸当然叫老三 } }老爸一看成绩单,听我这么一说,非常开心,儿子有进步呀,从 40 多名进步到 30 多名,进步很大,
躲过了一顿海扁。
相关文章推荐
- WEB服务器与应用服务器的区别
- Android自动化测试 - Monkey & Monkeyrunner
- __block和__weak的区别
- EM无法连接到数据库实例 解决方案
- Linux中Mysql字符集问题
- bittorrent优化
- 使用git微命令深入理解git工作机制
- JAVA对象的初始化过程
- yum install 时候提示错误 xxx 是 xxx 的副本
- The connection to adb is down, and a severe error has occured.
- C语言——池塘夜降彩色雨
- css中脱离文档流的理解
- Eclipse中Java Web项目自动部署到Tomcat服务器
- springmvc下Jersey 搭建RESTful服务
- Android自定义View之酷炫圆环(二)
- 程序无法运行:Error Default activity not found
- spring注解学习手册
- fold
- 重学C++ (二) 数组和指针
- 熔断危情