一、概述
装饰模式,动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。该模式以对客户端透明的方式扩展对象的功能。
1、什么时候使用
1) 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责;
2) 处理那些可以撤销的职责;
3) 当不能采用生成子类的方式进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
2、四大角色
1)抽象装饰对象角色(Component):接口,被装饰对象的基类,提供被装饰得方法,被装饰对象和装饰器都实现该接口;
2)具体装饰对象角色(ConcreteComponent):具体被装饰对象,它继承自Component,并实现需要被装饰的方法基本内容;
3)抽象装饰器角色(Decorator):抽象类,维持一个装饰对象实例的引用,所有具体装饰器对象的父类,完成装饰器的部分职能。可以只对被装饰的对象进行一些简单的包裹,也可包含对被装饰的对象中方法的实现;
4)具体装饰器角色(ConcreteDecorator):完成具体的装饰功能。装饰功能的实现是通过调用被装饰对象对应的方法,加上装饰对象自身的方法,这是装饰器模式动机中的添加额外功能的关键。可以有多个具体装饰角色,但是要注意各装饰之间的调用顺序。
二、代码示例
抽象装饰对象
public interface Person {
void doCoding();
}
被装饰对象及其基本方法
public class Employee implements Person {
@Override
public void doCoding() {
System.out.println("程序员实现功能需求");
}
}
抽象装饰器,指定一个装饰对象的引用
public abstract class Manager implements Person {
protected Person person;
public void doCoding() {
person.doCoding();
}
}
具体装饰器,指定该装饰器的装饰对象
public class ManagerA extends Manager {
public ManagerA(Person person) {
this.person = person;
}
@Override
public void doCoding() {
doEarly();
super.doCoding();
}
private void doEarly() {
System.out.println("项目经理A处理前期事项");
}
}
另一个具体装饰器
public class ManagerB extends Manager {
public ManagerB(Person person) {
this.person = person;
}
@Override
public void doCoding() {
super.doCoding();
doEnd();
}
private void doEnd() {
System.out.println("项目经理B处理后期事项");
}
}
测试代码
public class ClientMain {
public static void main(String args[]) {
Person employee = new Employee();
employee = new ManagerA(employee);//赋予程序猿项目经理A职责
employee = new ManagerB(employee);//赋予程序猿项目经理B职责
employee.doCoding();
}
}
输出:
项目经理A处理前期事项
程序员实现功能需求
项目经理B处理后期事项
如果将上面“赋予程序猿项目经理A职责”与“赋予程序猿项目经理B职责”执行顺序换一下,发现输出依然如上,没有改变。这里的主要原因是将Person这个被装饰对象,从一个装饰器传递到另一个装饰器了。
特点
1) 装饰者和被装饰者拥有相同的超类型(可能是抽象类也可能是接口);
2)在装饰类中包含一个被装饰组件类的对象引用;
3)可以为被装饰对象添加额外的功能;
4)在装饰类中重写被装饰组件类中的方法,并对被装饰组件类中对应的方法调用;
5)因为装饰者和被装饰者拥有相同的抽象类型,因此在任何需要原始对象(被包装)的场合,都可以用装饰过的对象来替代它;可以用多个装饰类来包装一个对象,装饰类可以包装装饰类或被装饰对象。简而言之,装饰模式保持接口,增强性能;继承至Component同时包含一个Component作为其成员变量(装饰器模式动机中的动态地增加功能是在这里实现的)。
参考:
https://blog.csdn.net/wuqingyidongren/article/details/51537790
https://www.cnblogs.com/chenxing818/p/4705919.html