概述
- 定义 : 在不改变原有对象的基础之上, 将功能附加到对象上
- 提供了比继承更有弹性的替代方案(扩展原有对象功能)
- 又叫包装器Wrapper, 适配器模式也被称之为包装器
- 类型 : 结构型
适用场景
- 扩展一个类的功能或给一个类添加附加职责
- 动态的给一个对象添加功能, 这些功能可以再动态的撤销
优点
- 继承放入有力补充, 比继承灵活, 在不改变原有对象的情况下给一个对象扩展功能
- 通过使用不同装饰类以及这些装饰类的排列组合, 可以实现不同效果
缺点
- 会出现更多的代码, 更多的类, 增加程序复杂性
- 动态装饰时, 多层装饰时更复杂
模式角色
-
Component : 定义一个对象接口,可以给这些对象动态地添加职责
-
ConcreteComponent : 定义一个对象,可以给这个对象添加一些职责
-
Decorator : 维持一个指向Component对象的引用,并定义一个与Component接口一致的接口, Java中通常是使用构造器接收Component, Java中通常装饰者类和被装饰的类实现同样的接口, 所以这个角色大多数时候就使用Component接口
-
ConcreteDecorator : 向组件添加职责, Java中代表包装类
代码实现
业务场景
有一个coffee接口, 有一个实现类coffee, 如果需要加一份牛奶的话, 就调用牛奶装饰器, 如果需要加糖的话, 就调用加糖的装饰器, 最终可以展示coffee中加了哪些东西, 加完之后的价格是多少
UML类图
代码实现
Icoffee接口:
/**
* 被装饰的类接口
* 这里也可以使用抽象类实现
* @author 七夜雪
* @create 2018-11-23 14:40
*/
public interface ICoffee {
public void showDesc();
public String getDesc();
public int getPrice();
}
Coffee类:
/**
* 普通的Coffee类
*
* @author 七夜雪
* @create 2018-11-23 14:41
*/
public class Coffee implements ICoffee {
private String desc = "一杯咖啡";
private int price = 20;
@Override
public void showDesc() {
System.out.println(desc + " 价格为:" + price);
}
@Override
public String getDesc() {
return desc;
}
@Override
public int getPrice() {
return price;
}
}
牛奶包装类:
/**
* 牛奶装饰类 : 表示向咖啡中加一份牛奶
*
* @author 七夜雪
* @create 2018-11-23 14:44
*/
public class MilkDecorator implements ICoffee {
private String desc;
private int price;
public MilkDecorator(ICoffee coffee) {
this.desc = coffee.getDesc() + " 加一份牛奶";
// 表示每加一份牛奶, 价格增加3元
this.price = coffee.getPrice() + 3;
}
@Override
public void showDesc() {
System.out.println(desc + " 价格为:" + price);
}
@Override
public int getPrice() {
return price;
}
@Override
public String getDesc() {
return desc;
}
}
糖包装类:
/**
* 糖装饰类 : 表示向咖啡中加一份糖
*
* @author 七夜雪
* @create 2018-11-23 14:44
*/
public class SugarDecorator implements ICoffee {
private String desc;
private int price;
public SugarDecorator(ICoffee coffee) {
this.desc = coffee.getDesc() + " 加一份糖";
// 表示每加一份牛奶, 价格增加2元
this.price = coffee.getPrice() + 2;
}
@Override
public void showDesc() {
System.out.println(desc + " 价格为:" + price);
}
@Override
public int getPrice() {
return price;
}
@Override
public String getDesc() {
return desc;
}
}
测试代码:
public static void main(String[] args) {
ICoffee coffee = new Coffee();
coffee = new MilkDecorator(coffee);
coffee = new SugarDecorator(coffee);
coffee = new SugarDecorator(coffee);
coffee.showDesc();
}
测试结果:
一杯咖啡 加一份牛奶 加一份糖 加一份糖 价格为:27