1 概述
当你在编写代码时,需要扩展一个类的功能,或者是当前类的接口不能满足需求时,你会选择怎么做?
- 重新编写子类,通过继承加入功能?
- 修改原有类的接口使其符合现有环境?
但你会发现这些改动是不完美的,它们并不符合面向对象的「
开放-关闭原则
」。
在软件设计模式中有一个更好的答案——包装
。
今天介绍的四种设计模式都围绕着“包装”展开,那么首先先简单了解一下这些设计模式:
装饰者模式
(Decorator Pattern
):包装另一个对象,并提供额外的行为适配器模式
(Adapter Pattern
):包装另一个对象,并提供不同的接口外观模式
(Facade Pattern
):包装许多对象以简化它们的接口代理模式
(Proxy Pattern
):包装另一个对象,并【控制】对它的访问
2 模式定义
装饰器模式
(Decorator Pattern
):动态地对一个对象添加额外的职责/行为。就增加功能来说,装饰器模式比生成子类更为灵活。
3 主要角色
4 样例代码/通用代码
案例1
Component
//Component定义了一个对象接口,通过装饰类可以给这些对象动态地添加职责
public abstract class Component {
public abstract void operation();
}
Decorator
/** Decorator,装饰抽象类,继承了Component
* 从外类来扩展Component类的功能,但对于Component来说,
* 是无需知道Decorator的存在的
*/
public abstract class Decorator extends Component {
protected Component component;
//获取被装饰的对象
public Component getComponent() {
return component;
}
//设置被装饰的对象
public void setComponent(Component component) {
this.component = component;
}
@Override
public void operation() {
if (component != null) {
component.operation();
}
}
}
ConcreteDecoratorX(A/B/C)
//具体装饰类,可以为类加入新的行为
class ConcreteDecoratorA extends Decorator {
private String addedState;
@Override
public void operation() {
// 首先运行原Component的operation(),再执行本类的功能,如addedState,相当于对原Component进行了装饰
super.operation();
addedState = "A中的new state ";
System.out.println(addedState + "具体装饰对象A的操作");
}
}
class ConcreteDecoratorB extends Decorator {
@Override
public void operation() {
super.operation();
addedBehavior();
System.out.println("具体装饰对象B的操作");
}
public void addedBehavior() {
System.out.print("B中的新增行为 ");
}
}
class ConcreteDecoratorC extends Decorator {
@Override
public void operation() {
super.operation();
System.out.println("C没有特殊行为 " + "具体装饰对象C的操作");
}
}
ConcreteComponent
//ConcreteComponent是定义一个具体的对象,也可以给这个对象添加一些职责
public class ConcreteComponent extends Component {
@Override
public void operation() {
System.out.println("具体对象的操作");
}
}
DecoratorClient
//装饰模式客户端调用代码
public class DecoratorClient {
public static void main(String[] args) {
ConcreteComponent concreteComponent = new ConcreteComponent();
//声明装饰类A、B、C
ConcreteDecoratorA concreteDecoratorA = new ConcreteDecoratorA();
ConcreteDecoratorB concreteDecoratorB = new ConcreteDecoratorB();
ConcreteDecoratorC concreteDecoratorC = new ConcreteDecoratorC();
//装饰的过程就像是层层包装,不断地装饰类包装对象,达到添加功能的目的
concreteDecoratorA.setComponent(concreteComponent); //装饰类A包装对象
concreteDecoratorB.setComponent(concreteDecoratorA); //装饰类B包装装饰类A(对象已经被包装在装饰类A中)
concreteDecoratorC.setComponent(concreteDecoratorB); //装饰类C包装装饰类B
concreteDecoratorC.operation();
}
}
5 模式特点
优点
缺点
装饰器模式与代理模式的区别
装饰器模式与建造者模式的区别
比起建造者模式,
建造者模式
必须过程稳定;而装饰器模式
是过程动态的。