Java设计模式之装饰者模式(Decorator)

1.简介

设计原则:开发-封闭  多组合少继承

指在不改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。他是通过创建一个包装对象,也就是装饰来包裹真实的对象。

  1. 特点:装饰对象和真实对象(被装饰的对象)具有相同接口;装饰对象包含一个真实对象的引用;装饰对象接受所有来自客户端的请求并转交真实对象;装饰对象可以在转发请求之前/后添加附加功能
  2. 组成
成分
抽象构建(Component) 角色:给出一个抽象接口,规范准备接收附加职责的对象
具体构建(Concrete Component) 角色:定义一个将要接收附加职责的类
装饰(Decorator)角色:内部持有一个构建Component对象的实例,并实现与抽象构建接口一致的接口
具体装饰(Concrete Decorator)角色:负责给构建对象添加附加的职责
  1. 优点:继承与装饰者模式的目的都是为了扩展类的功能,但是Decorator模式更加的灵活;通过使用不同的具体装饰类,可以排列(排列,组合)出更多不同的组合
  2. 缺点:更加多的复杂性;导致出现很多小类,使得程序变得复杂;

UML类图结构为:(引自百度百科)
Java设计模式之装饰者模式(Decorator)

2.使用场景

  • 需要扩展一个类的功能,或给一个类添加附加职责
  • 动态的给对象添加功能,可以动态的撤销
  • 需要增加由一些基本功能排列组合而成的非常大量的功能
  • 当不能采用生成子类的方法对类进行扩充时。a:类定义被隐藏或定义类不能生成子类;b:有大量的独立扩展

常用的IO流就是采用的装饰者模式

3.案例

抽象构建Component角色


//对象接口,动态的给对象添加功能
public interface Component {
    void operation();
}

具体构建ConcreteComponent角色


//具体的对象,要添加装饰的类
public class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("具体对象的操作");
    }
}

抽象装饰Decorator角色:


//装饰抽象类,实现装饰接口,从外类扩展Component的功能
public abstract class Decorator implements Component {
    //持有抽象构建角色的引用
    private Component component;

    public void setComponent(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        //先执行Component的operation
        if (this.component != null) {
            this.component.operation();
        }
    }
}

具体装饰ConcreteDecorator角色


//具体的装饰对象,起到给Component添加功能
public class ConcreteDecoratorA extends Decorator {
    @Override
    public void operation() {
        //先执行Component.operation
        super.operation();
        System.out.println("具体装饰对象A的操作");
    }
}

public class ConcreteDecoratorB extends Decorator {

    @Override
    public void operation() {
        super.operation();
        System.out.println("具体装饰对象B的操作");
    }
}

客户端使用

import java.io.FileOutputStream;

public class Main {
    public static void main(String[] args) {
        ConcreteComponent concreteComponent = new ConcreteComponent();
        ConcreteDecoratorA ca = new ConcreteDecoratorA();
        ConcreteDecoratorB cb = new ConcreteDecoratorB();
        ca.setComponent(concreteComponent);
        cb.setComponent(ca);
        cb.operation();
        //一次调用最先设置的
        System.out.println("");
        //更改顺序
        cb.setComponent(concreteComponent);
        ca.setComponent(cb);
        ca.operation();

    }
}

客户端使用时,可以随意的排列组合;实现各种各样的扩展功能。

模式简化

  1. 如果只有一个Concrete Component类而没有抽象的Component接口时,可以让Decorator继承Concrete Component。
  2. 如果只有一个Concrete Decorator类时,可以将Decorator和Concrete Decorator合并。

参考:
https://baike.baidu.com/item/装饰模式/10158540?fr=aladdin
《大话设计模式》