一 定义
装饰者模式又称包装模式,是指不改变原有对象的基础上,将功能附加到对象上,提供了比继承更有弹性的替代方案.属于结构型设计模式
比如在日常生活中,我们去买煎饼果子,会有一个基础的套餐,不同的人根据自己的喜好选择加不同的配料,比如加了一个鸡蛋装饰,就是鸡蛋煎饼果子,加一个火腿装饰,就是火腿煎饼果子.不管怎么加配料,它本质是一个煎饼,只是对煎饼进行了装饰而已
二 装饰者模式类图
- 抽象组件(Compent): 一个接口或抽象类 用于规定被装饰者的行为
- 具体组件(ConcreteCompent): 被装饰者 实现compent
- 抽象装饰器(decorator): 通用的ConcreteComponent装饰器,内部必有一个引用指向抽象组件Component,这个属性通常不是一个具体的实现,而是总的抽象组件接口,为了让其子类传入具体的实现类,这个类不是必须的,如果装饰逻辑比较单一,并不需要实现很多的装饰器,我们可以省略该类,直接写具体的装饰器(ConcreteComponentA…等)
- 具体装饰器(ConcreteComponentA…): Decorator的实现类,每一个实现类都扩展类component组件的一个功能
三 装饰者模式实现
定义抽象组件
public interface Battercake {
/**
* 描述
* @return
*/
String getMsg();
/**
* 价格
* @return
*/
int getPrice();
}
定义被装饰者
public class BaseBattercake implements Battercake{
@Override
public String getMsg() {
return "薄饼";
}
@Override
public int getPrice() {
return 5;
}
}
定义抽象装饰者
public abstract class BattercakeDecorator implements Battercake{
/**
* 被装饰的实际对象
*/
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() + "加一个鸡蛋";
}
@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() + "加一个火腿";
}
@Override
public int getPrice() {
return super.getPrice() +3;
}
}
客户端调用
public class Client {
public static void main(String[] args) {
// 创建基础套餐
Battercake baseBattercake = new BaseBattercake();
// 加一个鸡蛋
BattercakeDecorator eggBattercake = new EggBattercake(baseBattercake);
// 加一个火腿
BattercakeDecorator hamBattercake = new HamBattercake(eggBattercake);
System.out.println(hamBattercake.getMsg());
System.out.println(hamBattercake.getPrice());
}
}
运行结果
薄饼加一个鸡蛋加一个火腿
10
四 源码中的应用
五 总结
优点:
- 装饰器是继承的有力补充,不改变原有对象的情况下给对象扩展功能,像插件一样即插即用.
- 遵守开闭原则,里式替换原则,依赖倒置原则
缺点:
- 会产生更多的类,增加程序复杂性