设计模式——装饰模式

本文主要参考资料:《设计模式之禅》

辅助教程:https://www.cnblogs.com/stonefeng/p/5679638.html

本文主要目录为:
1)案例

2)装饰模式改进案例

3)装饰模式的定义

 

 

 

1.  案例

 

小学的时候成绩很差,到了四年级的时候,学校突然把成绩单打印出来让我们带回去给父亲签字。具体的类图和代码如下所示

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("尊敬的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);
	}

}
public class Father {
	
	public static void main(String[] args) {
		//成绩单拿过来
		SchoolReport sr = new FouthGradeSchoolReport();		
		//看成绩单
		sr.report();		
		//签名?休想!
	}
}

成绩单一出来,你别看什么62,65之类的成绩,你要知道,在小学低于90分基本就是中下了。这个成绩还找老爸签字?准备挨揍吧!

 

 

2. 装饰模式改进案例

但我当时并没有直把成绩单交给我老爸,而是在他之前做了点技术,我要把成绩单封装一下,封装分为两步来实现,如下图所示:

我们通过增加一个子类SugarFouthGradeSchoolReport继承FouthGradeReport,重写report方法,确实能解决问题。但现实的情况很复杂:可能老爸听了我汇报最高成绩以后,就直接乐开了花,直接签名了后面的排名就没有必要看,或则老爸先要看排名情况,那怎么办?继续扩展?你能扩展几个类?这还是一个比较简单的场景,一旦需要装饰的条件非常多,比如20个,就会出现类爆炸的情况,而且以后维护困难,谁愿意维护一大滩本质相似的代码?并且,在面向对象的设计中,如果超过两层继承,你就应该想想是不是设计出了问题(不绝对),继承的层次越多以后维护的成本就越多。

        所以我们现在需要定义一批专门负责装饰的类,然后根据实际情况来决定是否需要进行装饰:

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("尊敬的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);
	}
}
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);
	}	
}
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();
	}
}
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();
	}
}
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("老三");  //我叫小三,老爸当然叫老三
	}
}

 

3. 装饰模式的定义

定义:Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.(动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生产子类更为灵活。)

装饰模式的通用类图如下图:

在类图中,有四个角色需要说明:

  • Component抽象构件:Component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象。
  • ConcreteComponent具体构件:ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,你要装饰的就是它。
  • Decorator装饰角色:一般是一个抽象类,做什么用呢?实现接口或者抽象方法,它里面可不一定有抽象的方法呀,在它的属性里必然有一个private变量指向Component抽象构件。
  • 具体装饰对象:ConcreteDecorator1和ConcreteDecorator2是两个具体的装饰类,你要把最核心的、最原始的、最基本的东西装饰城其他东西。

装饰模式的应用

1.装饰模式的优点

  • 装饰类与被装饰类可以独立发展,而不会耦合。换句话说,Component类无须知道Decorator类,Decorator类是从外部来扩展Component类的功能,而Decorator类也不用知道具体的构件。
  • 装饰模式时继承关系得一个替代方案。我们看装饰类Decorator,不管装饰多少层,返回的对象还是Component,实现的还是is-a的关系。
  • 装饰模式可以动态地扩展一个实现类得功能。

2.装饰模式的缺点

对于装饰模式记住一点就足够了:多层的装饰是很复杂的。因此,尽量减少装饰类的数量,以便降低系统的复杂度。

3.装饰模式的使用场景

  • 需要扩展一个类的功能,或给一个类增加附加功能。
  • 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
  • 需要为一批的兄弟类进行改装或加装功能,当然是首选装饰模式。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值