设计模式 - 装饰模式(Decorator)
设计模式 - 装饰模式(Decorator)
装饰模式(Decorator)的概念
- 装饰模式又叫包装模式。
- 装饰模式以对客户端透明的方式扩展对象的功能,对象功能包括属性方法等,相比继承关系是类的扩展。
- 装饰模式以对客户端透明的方式动态的给一个对象附加更多的功能,客户端不会感觉到对象在装饰前和装饰后有什么不同。
- 装饰模式可以在不创建更多子类的情况下,将对象的功能加以扩展。
装饰模式(Decorator)的角色
- 抽象构件角色:给出一个抽象接口,以规范准备接收附加责任的对象。
- 具体构件角色:定义一个将要接收附加责任的类。
- 装饰角色:持有一个构件对象的引用,并定义一个与抽象构建接口一直的接口
- 具体装饰角色:负责给构件对象添加附加的责任。
装饰模式(Decorator)的特点
- 装饰对象和真实对象拥有相同的接口。
- 装饰对象包含一个真实对象的引用。
- 装饰对象接收所有来自客户端的请求。
- 装饰对象可以在转发这些请求以前或者以后添加一些附件的功能。
上述都是一些纯理论的知识,很难去真正的理解和在实际工作中运用,下面我们可以通过例子去展示,然后在回过头来在看上述的理论知识可能会理解深刻一点。
装饰模式(Decorator)的例子
- 抽象构件角色
/**
* 抽象构件角色
*/
public interface Componet {
/**
* 定义doSomething方法
*/
void doSomething();
}
- 具体构件角色
/**
* 具体构件角色
*/
public class ConcreteComponent implements Componet {
@Override
public void doSomething() {
System.out.println("功能A");
}
}
- 装饰角色
/**
* 装饰角色
* 1 实现抽象构件角色 Componet
*/
public class Decorator implements Componet {
/**
* 2 持有实现抽象构件角色的引用
*/
private Componet componet;
public Decorator(Componet componet) {
this.componet = componet;
}
@Override
public void doSomething() {
/**
* 实现有componet引用进行执行
*/
componet.doSomething();
}
}
- 具体装饰角色 1
/**
* @author: mahan
* @date: 2019/5/20
* @Description:
**/
public class ConreteDecirator1 extends Decorator {
public ConreteDecirator1(Componet componet) {
super(componet);
}
@Override
public void doSomething() {
//执行父类doSomething
super.doSomething();
//添加额外的功能
this.doAnotherThing();
}
private void doAnotherThing() {
System.out.println("功能B");
}
}
- 具体装饰角色 2
/**
* @author: mahan
* @date: 2019/5/20
* @Description:
**/
public class ConreteDecirator2 extends Decorator {
public ConreteDecirator2(Componet componet) {
super(componet);
}
@Override
public void doSomething() {
//执行父类doSomething
super.doSomething();
//添加额外的功能
this.doAnotherThing();
}
private void doAnotherThing() {
System.out.println("功能C");
}
}
- 测试
public class Test {
public static void main(String[] args) {
Componet componet3 = new ConreteDecirator2(new ConreteDecirator1(new ConcreteComponent()));
//实现三个功能
componet3.doSomething();
System.out.println("-----------------");
Componet componet2 = new ConreteDecirator1(new ConcreteComponent());
//实现二个功能
componet2.doSomething();
System.out.println("-----------------");
Componet componet1 = new ConcreteComponent();
//实现一个功能
componet1.doSomething();
}
}
- 结构
功能A
功能B
功能C
-----------------
功能A
功能B
-----------------
功能A
适用场景
- 想要透明并且动态的给对象添加新的功能而不影响其他对象
- 给对象添加的职责在未来可能会发生变化
- 用子类扩展功能不实际的情况下