一、前言
当前的系统设计无法满足我的需求,急需动态的添加更多是功能的时候,我们选择装饰模式来完成这一项任务,我们知道通过继承也可以是实现功能的添加,如果依赖继承,那么类的行为只能在编译时静态决定,换句话说,行为如果不是来自超类,就是来自子类覆盖后的版本,同时,我们还要修改现有的代码。
二、定义
装饰模式在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
三、类图
四、举例
在生活中我们也有很多的生活场景类似于装饰模式的使用。结合在网上看到的其他案例,以手抓饼为例来阐述装饰模式。
首先我们将手抓饼提取为一个抽象类或者接口来实现不太配料手抓饼的制作。Java语言仅支持单继承,我们这里就使用接口来说明。
/**
* 手抓饼接口,所以的手抓饼都出自该接口
*
*/
public interface Pancake {
public String getDesc();//对该手抓饼的描述
public double getPrice();//该手抓饼的价格
}
这个接口就是抽象组件Component,也是一个类的基本功能。
下面我们实现该接口,来生产没有任何配菜的低配手抓饼
/**
* 低配手抓饼,只有一个饼,价格为4元
*
*/
public class BasePancake implements Pancake {
@Override
public String getDesc() {
return "饼";
}
@Override
public double getPrice() {
return 4;
}
}
我们可以看到低配手抓饼(ConcreteComponent,抽象组件的具体实现)什么也没有加,只有一个饼,价格为4元。
当我们想给手抓饼添加各种配料并且计算出不同的价格,我们需要一个装饰接口来继承Component.。
/**
* 手抓饼的加项类,该处继承手抓饼接口时为了达到“类型匹配”而不是获得“行为”
*
*/
public interface Charge extends Pancake {
//这里也可以添加新的方法
}
这里继承了Component是为了实现类型匹配,所以在这个接口里面,我们什么也没有做。
下面,我们需要具体的装饰类来装饰ConcreteComponent
/**
* 加项鸡蛋类,该类实现了装饰接口Charge
*
*/
public class Egg implements Charge {
Pancake pancake;//内部持有手抓饼的基类
/*
* 在构造的时候实例化手抓饼的类型
* */
public Egg(Pancake pancake) {
this.pancake = pancake;
}
@Override
public String getDesc() {
return pancake.getDesc()+"加鸡蛋";
}
这里有一个鸡蛋类,实现类装饰接口Charge,内部持有一个手抓饼对象,并且在构造函数中来实例化该对象。
测试:
public static void main(String[] args) {
//首先购买一个低配的手抓饼,即什么都不加,只有一个饼
BasePancake basePancake=new BasePancake();
System.out.println("我购买的手抓饼是:"+basePancake.getDesc()+",价格是:"+basePancake.getPrice());
//购买一个加鸡蛋的饼
Egg egg=new Egg(basePancake);
System.out.println("我购买的手抓饼是:"+egg.getDesc()+",价格是:"+egg.getPrice());
}
************************************************************************
我购买的手抓饼是:饼,价格是:4.0
我购买的手抓饼是:饼加鸡蛋,价格是:5.0
如果我们需要增加更多的配料,我们只需要增加一些配料类来实现Charge接口,无需修改其他代码。
五、优缺点
优点:
装饰者模式充分体现了对修改关闭,对拓展开放的开闭原则,装饰着可以在被装饰的行为前面或者后面加上自己的行为,甚至将被装饰者的行为完全取代,从而达到特定的目的。
缺点:
但是装饰者在设计的过程中会出现许多小对象,如果过度使用装饰者,会让程序变的复杂。装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出较佳选择。
六、使用场景
1、动态、透明的给对象添加职责;
2、有的一组基本功能进行排列组合而产生非常多的功能时;