Java设计模式之装饰者模式(Decorator)
1.简介
设计原则:开发-封闭 多组合少继承
指在不改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。他是通过创建一个包装对象,也就是装饰来包裹真实的对象。
- 特点:装饰对象和真实对象(被装饰的对象)具有相同接口;装饰对象包含一个真实对象的引用;装饰对象接受所有来自客户端的请求并转交真实对象;装饰对象可以在转发请求之前/后添加附加功能
- 组成:
成分 |
---|
抽象构建(Component ) 角色:给出一个抽象接口,规范准备接收附加职责的对象 |
具体构建(Concrete Component ) 角色:定义一个将要接收附加职责的类 |
装饰(Decorator )角色:内部持有一个构建Component 对象的实例,并实现与抽象构建接口一致的接口 |
具体装饰(Concrete Decorator )角色:负责给构建对象添加附加的职责 |
-
优点:继承与装饰者模式的目的都是为了扩展类的功能,但是Decorator模式更加的
灵活
;通过使用不同的具体装饰类,可以排列(排列,组合)
出更多不同的组合 - 缺点:更加多的复杂性;导致出现很多小类,使得程序变得复杂;
UML类图结构为:(引自百度百科)
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();
}
}
客户端使用时,可以随意的排列组合;实现各种各样的扩展功能。
模式简化:
- 如果只有一个Concrete Component类而没有抽象的Component接口时,可以让Decorator继承Concrete Component。
- 如果只有一个Concrete Decorator类时,可以将Decorator和Concrete Decorator合并。
参考:
https://baike.baidu.com/item/装饰模式/10158540?fr=aladdin
《大话设计模式》