今天继续学习CBF4LIFE的设计模式,看到了第13章-----装饰模式。以前看thinking in Java中IO部分,讲到IO管道之间的套接时,作者就说到了此处运用到了装饰模式,当时没太留意什么装饰模式到底是个啥玩意,今天再次接触到它,以免以后忘记了,还是写下来为妙啊。
CBF4LIFE中装饰模式中,举到的“修饰”成绩单的例子很是经典,在这里,我也就照搬啦(故事情节太长,这里主要是看里氏替换原则使用,在此就不用祥讲了)。
先定义抽象的学生成绩单
package com.lonton.decorator;
public abstract class SchoolReport {
public abstract void report();
public abstract void sign(String name);
}
填写成绩单的内容
package com.lonton.decorator;
/**
*
* @author opalshine
*
*/
public class FouthGradeSchoolReport extends SchoolReport {
@Override
public void report() {
System.out.println("尊敬的XXX家长:");
System.out.println(" ......");
System.out.println(" 语文 62 数学65 体育 98 自然 63");
System.out.println(" .......");
System.out.println(" 家长签名: ");
}
@Override
public void sign(String name) {
System.out.println("家长签名为:"+name);
}
}
拿回家给老爸签名
package com.lonton.decorator;
public class Father {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
SchoolReport sr = new FouthGradeSchoolReport();
sr.report();
sr.sign("爸爸");
}
}
成绩单啥样
尊敬的XXX家长:
......
语文 62 数学65 体育 98 自然 63
.......
家长签名:
这成绩,老爸气的够呛的,还会给你签名吧,首先准备挨板子吧。当然咯,为了避免一顿板子,我首先得将成绩单修饰修饰哈
定义修饰模板
package com.lonton.decorator;
/**
* Decorator抽象类的目的很简单,就是要让Decorator子类来封装SchoolReport的子类
* @author opalshine
*
*/
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);
}
}
怎么修饰呢?弄虚作假肯定不行,那样被发现了,那就不是一顿板子的事咯。其实这次考试成绩都不高,语文最高分75,数学
78,自然80,嘿嘿,我那60几分跟最高分也差不了多少了(其实也是最后几名啊),另外,班上转学了10几个人,我的排名也
理 所当然的前进了十几名,排到38名了(这个当然就不必和老爸说了)
定义最高分数模板
package com.lonton.decorator;
public class HighScoreDecorator extends Decorator {
public HighScoreDecorator(SchoolReport sr) {
super(sr);
}
private void reportHighScore(){
System.out.println("这次考试语文最高分75,数学78,自然80");
}
public void report(){
this.reportHighScore();
super.report();
}
}
定义排名模板
package com.lonton.decorator;
public class SortDecorator extends Decorator {
public SortDecorator(SchoolReport sr) {
super(sr);
// TODO Auto-generated constructor stub
}
private void reportSort(){
System.out.println("我这次排名38----");
}
public void report(){
super.report();
this.reportSort();
}
}
然后,老爸看到的成绩单就不一样咯
package com.lonton.decorator;
/**
* @author opalshine
*
*/
public class Father {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
SchoolReport sr = new FouthGradeSchoolReport();
/**里氏替换原则,基类能出现的地方,子类也一定能够出现
* 里氏替换原则,父类引用指向子类对象
* HighSocreDecorator构造函数中的参数应该是SchoolReport,但这里却是SchoolReport的子类FouthGradeSchoolReport
* 同样,SortDecorator构造函数中的参数也应该是SchoolReport,但是这里却是HighScoreDecorator
* 装饰模式中,充分的体现出了里氏替换原则
*
*/
sr = new HighScoreDecorator(sr);
sr = new SortDecorator(sr);
sr.report();
sr.sign("爸爸");
}
}
这次考试语文最高分75,数学78,自然80
尊敬的XXX家长:
......
语文 62 数学65 体育 98 自然 63
.......
家长签名:
我这次排名38----
家长签名为:爸爸
以高兴,爽快的签了名。嘿嘿,我理解的运用到的里氏替换原则在Father类注释也说明了。