一、 什么是装饰者模式
装饰者模式又称包装模式,是指不改变原有对象的基础上,将功能附加到对象上,提供了比继承更有弹性的替代方案.属于结构型设计模式.
二、装饰者模式uml图
装饰器其中包含4个角色:
抽象组件(Component): 可以是一个接口或者抽象类,规定了被装饰者的行为.
具体组件(ConcreteComponent): 实现或继承(component)的一个具体对象.也即被装饰者.
抽象装饰器(decorator): 通用的ConcreteComponent装饰器,内部必有一个引用指向抽象组件Component,这个属性通常不是一个具体的实现,而是总的抽象组件接口,为了让其子类传入具体的实现类,这个类不是必须的,如果装饰逻辑比较单一,并不需要实现很多的装饰器,我们可以省略该类,直接写具体的装饰器(ConcreteComponentA…等)
具体装饰器(ConcreteComponentA…),Decorator的实现类,每一个实现类都扩展类component组件的一个功能.
三、实现自己的装饰者代码
现实场景
现实场景当中其实也有装饰者模式,我们生活中的去买煎饼果子的时候,如果我们什么都不加,会有一个默认加料(比如,里面只有一个鸡蛋).其实就相当于上面的具体组件.我们也可以加,火腿,培根,鸡柳…,其实就相当于一个个的装饰器.
代码
抽象组件:
/**
* 煎饼果子的抽象
*/
public abstract class Battercake {
/**
* 煎饼果子的总的配料信息
* @return
*/
public abstract String getMsg();
/**
* 总的价格
* @return
*/
public abstract int getPrice();
}
具体组件:
/**
* 基本套餐
*/
public class BaseBattercake extends Battercake{
@Override
public String getMsg() {
return "煎饼";
}
@Override
public int getPrice() {
return 5;
}
}
抽象装饰器
/**
* 煎饼果子的装饰抽象器
*/
public abstract class BattercakeDecorator extends Battercake {
private Battercake battercake;
public BattercakeDecorator(Battercake battercake) {
this.battercake = battercake;
}
@Override
public String getMsg() {
return battercake.getMsg();
}
@Override
public int getPrice() {
return battercake.getPrice();
}
}
具体装饰器:
/**
* 加鸡蛋的装饰器
*/
public class EggBattercake extends BattercakeDecorator {
public EggBattercake(Battercake battercake) {
super(battercake);
}
@Override
public String getMsg() {
return super.getMsg()+"+1个鸡蛋";
}
@Override
public int getPrice() {
return super.getPrice()+2;
}
}
/**
* 加火腿的装饰器
*/
public class HamBattercake extends BattercakeDecorator {
public HamBattercake(Battercake battercake) {
super(battercake);
}
@Override
public String getMsg() {
return super.getMsg()+"+1跟火腿";
}
@Override
public int getPrice() {
return super.getPrice()+1;
}
}
客户端调用
public class Test {
public static void main(String[] args) {
BaseBattercake baseBattercake = new BaseBattercake();
// 加一个火腿
HamBattercake hamBattercake = new HamBattercake(baseBattercake);
// 加一个鸡蛋
EggBattercake eggBattercake = new EggBattercake(hamBattercake);
System.out.println(eggBattercake.getMsg()+" 价格:"+eggBattercake.getPrice());
}
}
uml图
四、源码使用场景
我们经常说到的装饰器模式代表就是java中的io流,我们看下uml 图.
简单的看下输入流:
InputStream: 就是抽象组件
FilterInputStream: 就是抽象装饰器
FileInputStream: 就是具体组件
BufferedInputStream:就是具体装饰器
当然还有很多的具体装饰器,不做展开.
五、优点和缺点
优点
- 装饰器是继承的有力补充,不改变原有对象的情况下给对象扩展功能,像插件一样即插即用.
- 遵守开闭原则,里式替换原则,依赖倒置原则
缺点
- 会产生更多的类,增加程序复杂性