1. 装饰者模式
1.1 小明今年四年级,他的期末考试成绩单出来了(语文 62 数学 65 体育 98 自然 63),需要老爸给他签字,于是他去找老爸了:
public abstract class SchoolReport {
public abstract void report();
public abstract void sign(String name);
}
public class FouthGradeSchoolReport extends SchoolReport{
public void report() {
System.out.println("尊敬的***家长:");
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);
}
}
public class Father {
public static void main(String[] args) {
SchoolReport report = new FouthGradeSchoolReport();
report.report();
}
}
尊敬的xxx家长:
………..
语文 62 数学 65 体育 98 自然 63
………..
家长签名:
1.2 由于他的成绩相当不给力,老爸不但没有给他签字还把他屁股打了。所以他就对成绩单稍微装饰一下,再给老爸看。
他从两个方面对成绩单进行了装饰:
1. 汇报最高成绩:语文 75,数学 78,自然 80
2. 汇报排名情况:排名38名
用SugarFouthGradeSchoolReport装饰一下FouthGradeSchoolReport.
abstract class SchoolReport{
public abstract void report();
public abstract void sign(String name);
}
class FouthGradeSchoolReport extends SchoolReport{
@Override
public void report() {
System.out.println("尊敬的***家长:");
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);
}
}
class SugarFouthGradeSchoolReport extends FouthGradeSchoolReport{
public void reportHighScore() {
System.out.println("各个科目的最高分:语文75,数学78,自然 80");
}
public void reportSort() {
System.out.println("在班里排名38名");
}
public void report(){
this.reportSort();
this.reportHighScore();
super.report();
}
}
public class Father {
public static void main(String[] args) {
SchoolReport report = new SugarFouthGradeSchoolReport();
report.report();
}
}
在班里排名38名
各个科目的最高分:语文75,数学78,自然 80
尊敬的XXX家长:
………..
语文 62 数学 65 体育 98 自然 63
………..
家长签名:
这样小明的老爸看到小明的成绩跟全班最高的成绩相比差别不是很大,排名也还没有倒数,于是大笔一挥给他签了字。
1.3 这时小明考虑到了一个问题,如果老爸看完最高分,然后再看成绩单,就高兴的给签了字怎么办呢?小明有n种方式来装饰这个成绩单,那他怎么来适应这个需求呢?问题点在于装饰是可变,它是N种组合。于是他这样重新装饰了一下成绩单:
abstract class SchoolReport {
public abstract void report();
public abstract void sign(String name);
}
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);
}
}
abstract class Decorator extends SchoolReport{
private SchoolReport report;
public Decorator(SchoolReport report) {
super();
this.report = report;
}
public void report(){
this.report.report();
}
public void sign(String name){
this.report.sign(name);
}
}
class SortDecorator extends Decorator{
public SortDecorator(SchoolReport report) {
super(report);
}
public void report(){
super.report();
this.reportSort();
}
private void reportSort(){
System.out.println("在班里排名38名");
}
}
class HighScoreDecorator extends Decorator{
public HighScoreDecorator(SchoolReport report) {
super(report);
}
public void report(){
this.reportHighScore();
super.report();
}
private void reportHighScore(){
System.out.println("各个科目的最高分:语文75,数学78,自然 80");
}
}
public class Father {
public static void main(String[] args) {
SchoolReport report = new FouthGradeSchoolReport();
new SortDecorator(new HighScoreDecorator(report)).report();
report.sign("xxx");
System.out.println("=============华丽丽的分割线===============");
report.report();
}
}
各个科目的最高分:语文75,数学78,自然 80
尊敬的xxx家长:
………..
语文 62 数学 65 体育 98 自然 63
………..
家长签名:
在班里排名38名
家长签名:xxx
=============华丽丽的分割线===============
尊敬的xxx家长:
………..
语文 62 数学 65 体育 98 自然 63
………..
家长签名:
这样小明就可以只给老爸看最高成绩了
小结:
- 装饰类和被装饰类可以独立发展,而不会相互耦合。只要被装饰在同一个继承体系下,装饰类就可以对其进行装饰。
- 装饰模式是继承关系的一个替代方案。继承是打破封装,继承的层次越多,维护成本就越高。
- 多层的装饰比较复杂。就像洋葱一样,包的越多,剥的越多。
2. 代理模式VS 装饰模式
对于两个模式来说,装饰模式就是代理模式的一个特殊应用,两者的共同点是都具有相同的接口,不同点是代理模式着重对代理过程的控制,而装饰模式则是对类的功能的增强或减弱。
唯一的区别是什么?
装饰类对类的行为没有决定权,只有增强作用,也就是说它不决定被代理类的方式是否执行,它只是在此增加被代理类的功能。
代理模式是把当前的行为或者功能委托给其他对象执行,代理类负责接口限定,要不要调用真实的角色,是由代理类来决定的,它不对被代理类的功能做任何改变,保证是原汁原味的调用。
装饰模式是在保证接口不变的情况下加强类的功能,他保证的是被修饰的对象功能比原来的对象要丰富(当然有也可以使减弱),但不做准入条件的判断和准入条件的过滤,是否要执行,这些都不是装饰类所关心。