装饰者模式
- 装饰者模式指的是在不改变原文件和不使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装类对象,也就是装饰着来包裹真实的对象实现的
因此装饰者可以动态地将责任附加到对象上,提供了比继承更有弹性的扩展功能的方案
结构
- 组成结构
- 抽象构件(Component):给出抽象接口或抽象类,以规范准备接收附加功能的对象
- 具体构件(ConcreteComponent):定义将要接收附加功能的类
- 抽象装饰(Decorator):装饰者共同要实现的接口,也可以是抽象类,是抽象构件类的子类,维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法
- 具体装饰(ConcreteDecorator):持有一个 Component 对象,负责给构件对象贴上附加的功能
- UML
实现
代码示例
// 1. 声明一个原始对象的接口
public interface ICoffee {
void makeCoffee();
}
// 2. 构建原始对象(原味咖啡,实现了 ICoffee 接口)
public class OriginalCoffee implements ICoffee {
@Override
public void makeCoffee() {
System.out.print("原味咖啡 ");
}
}
// 3. 构件装饰者抽象基类,实现与原对象相同的接口 ICoffee,内部持有一个 ICoffee 类型引用,用来接收被装饰的对象
public abstract class CoffeeDecorator implements ICoffee {
private ICoffee coffee;
public CoffeeDecorator(ICoffee coffee){
this.coffee=coffee;
}
@Override
public void makeCoffee() {
coffee.makeCoffee();
}
}
// 4. 构建各种装饰者类,都继承自装饰者基类 CoffeeDecorator
// 加奶的装饰者
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(ICoffee coffee) {
super(coffee);
}
@Override
public void makeCoffee() {
super.makeCoffee();
addMilk();
}
private void addMilk(){
System.out.print("加奶 ");
}
}
// 加糖的装饰者
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(ICoffee coffee) {
super(coffee);
}
@Override
public void makeCoffee() {
super.makeCoffee();
addSugar();
}
private void addSugar(){
System.out.print("加糖");
}
}
// 5. 客户端使用
public static void main(String[] args) {
//原味咖啡
ICoffee coffee=new OriginalCoffee();
coffee.makeCoffee();
System.out.println("");
//加奶的咖啡
coffee=new MilkDecorator(coffee);
coffee.makeCoffee();
System.out.println("");
//先加奶后加糖的咖啡
coffee=new SugarDecorator(coffee);
coffee.makeCoffee();
}
特点
- 优点
提供比继承更加灵活的方式扩展对象的功能,通过排列组合可以对某个类的一些对象做动态的功能扩展,不需要装饰的对象则可以保持原样 - 缺点
类的个数会增加,产生很多装饰者类,增加系统复杂度 - 装饰者模式和代理模式的区别
一般认为代理模式侧重于使用代理类增强被代理对象的访问,而装饰者模式侧重于使用装饰者类对被装饰对象的功能进行增强
装饰者模式主要提供一组装饰者类,然后形成一个装饰者栈,动态的对某一个对象不断加强
代理模式一般不会使用多级代理