装饰模式

56 阅读4分钟

Decorator

别名:包装模式( Wrapper )

定义

允许通过将对象放入包含行为的特殊封装对象中来对原对象绑定新的行为。

核心:在不改变一个对象本身的基础上,添加额外的行为

应用场景

1.希望在无需修改代码的情况下即可使用对象,且希望在运行时为对象新增额外的行为。

装饰能将业务逻辑组织为层次结构, 你可为各层创建一个装饰, 在运行时将各种不同逻辑组合成对象。 由于这些对象都 遵循通用接口, 客户端代码能以相同的方式使用这些对象。

2.用继承来扩展对象行为的方案难以实现或根本不可行。

许多编程语言使用 final 最终关键字来限制对某个类的进一步扩展。 复用最终类已有行为的唯一方法是使用装饰模式: 用封装器对其进行封装。

3.处理可以撤销的职责

实现方法

1.确保业务逻辑可用一个基本组件及多个额外可选层次表示。

2.找出基本组件和可选层次的通用方法。 创建一个组件接口并在其中声明这些方法。

3.创建一个具体组件类, 并定义其基础行为。

4.创建装饰基类, 使用一个成员变量存储指向被封装对象的引用。 该成员变量必须被声明为组件接口类型, 从而能在运行 时连接具体组件和装饰。 装饰基类必须将所有工作委派给被 封装的对象。

5.确保所有类实现组件接口。

6.将装饰基类扩展为具体装饰。 具体装饰必须在调用父类方法(总是委派给被封装对象) 之前或之后执行自身的行为。

7.客户端代码负责创建装饰并将其组合成客户端所需的形式。

优缺点

优点:

1.你无需创建新子类即可扩展对象的行为。

2.你可以在运行时添加或删除对象的功能。

3.你可以用多个装饰封装对象来组合几种行为。

4.单一职责原则。 你可以将实现了许多不同行为的一个大类拆 分为多个较小的类。

缺点:

1.在封装器栈中删除特定封装器比较困难。 ​ 2.实现行为不受装饰栈顺序影响的装饰比较困难。 ​ 3.各层的初始化配置代码看上去可能会很糟糕。

结构

UML图

classDiagram
Client-->Component
Component <|.. ConcreteComponent
BaseDecorator o-->Component
BaseDecorator ..|>Component
ConcreteDecorators -- |>BaseDecorator
class Component{
<<interface>>
	+execute()
}
class ConcreteComponent{
	...
	+execute()
}
class BaseDecorator{
 	-wrappee:Component
 	+BaseDecrorator(c:Component)
 	+execute()
}
class ConcreteDecorators{
	...
	+execute()
	+extra()
}

参与者

1.部件( Component ) :声明封装类和被封装对象的公用接口

2.具体部件( Concrete Component ) : 类是被封装对象所属的类。它定义了基础行为,但装饰类可以改变这些行为。

3.基础装饰( Base Decorator ) : 类拥有一个指向被封装对象的引用成员变量。该变量的类型应当被声明为通用部件接口,这样它就可以引用具体的部件和装饰。装饰基类会将所有操作委派给被封装的对象

4.具体装饰类 ( Concrete Decorators ) :定义了可动态添加到部件的额外行为。具体装饰类会重写装饰基类的方法,并在调用父类方法之前或之后进行额外的行为。

5.客户端( Client ) :可以使用多层装饰来封装部件,只要它能使用通用接口与所有对象互动即可。

通用写法

//组件
public abstract class Component {
   public abstract void operation();
}
​
public class ConcreteComponent extends Component{
   @Override
   public void operation() {
       System.out.println("处理业务逻辑");
  }
}
​
//装饰
public class BaseDecorator extends Component{
   //持有组件对象
   protected Component component;
​
   public BaseDecorator(Component component){
       this.component = component;
  }
​
   @Override
   public void operation() {
       //请求转发至组件 进行操作[也可进行一些附加操作]
       System.out.println("将操作转给组件");
       component.operation();
  }
}
​
public class ConcreteDecoratorA  extends BaseDecorator{
   public ConcreteDecoratorA(Component component){
       super(component);
  }
​
   private void operationFirst(){
       System.out.println("执行前进行一系列操作");
  }
   private void operationLase(){
       System.out.println("执行后对数据进行处理");
  }
​
   @Override
   public void operation() {
       operationFirst();
​
       super.operation();
​
       operationLase();
  }
}
​
public class Client {
   public static void main(String[] args) {
       Component component = new ConcreteComponent();
       BaseDecorator decorator = new ConcreteDecoratorA(component);
       decorator.operation();
  }
}