定義
裝飾模式(Decorator Pattern)的定義如下:
Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.
動態地給一個對象添加一些額外的職責。就增加功能來說,裝飾模式相比生成子類更爲靈活。
裝飾械的通用類圖如下:
在類圖中,有四個角色需要說明:
-
Component抽象構件
Component是一個接口或者是抽象類,就是定義我們最核心的對象,也就是最原始的對象。 -
ConcreteComponent具體構件
ConcreteComponent是最核心、最原始、最基本的接口或抽象類的實現,你要裝飾的就是它。 -
Decorator裝飾角色
一般是一個抽象類,實現接口或者抽象方法,它裏面可不一定有抽象的方法,在它的屬性裏必然有一個private變量指向Component抽象構件。 -
具體裝飾角色
你要把你最核心的,最原始的、最基本的東西裝飾成其他東西。
抽象構件代碼:
public abstract class Component {
// 抽象的方法
public abstract void operate();
}
具體構件
public class ConcreteComponent extends Component {
// 具體實現
@Override
public void operate() {
System.out.println("do something");
}
}
裝飾角色通常是一個抽象類,代碼如下:
public abstract class Decorator extends Component {
private Component component = null;
// 通過構造函數傳遞被修飾者
public Decorator(Component _component) {
this.component = _component;
}
// 委託給被修飾者執行
@Override
public void operate() {
this.component.operate();
}
}
具體的裝飾類:
public class ConcreteDecorator1 extends Decorator {
// 定義被修飾者
public ConcreteDecorator1(Component _component) {
super(_component);
}
// 定義自己的修飾方法
private void method1() {
System.out.println("method1 修飾");
}
// 重寫父類的Operatio方法
public void operate() {
this.method();
super.operate();
}
}
場景類:
public class Client {
public static void main(String[] args) {
Component component = new ConcreteComponent();
// 第一次修飾
component = new ConcreteDecorator1(component);
// 第二次修飾
component = new ConcreteDecorator2(component);
// 修飾後運行
component.operate();
}
}
優點
- 裝飾類和被裝飾類可以獨立發展,而不會相互耦合;
- 裝飾類是繼承關係的一個替代方案;
- 裝飾模式可以動態地擴展一個實現類的功能;
缺點
多層的裝飾是比較複雜的。
爲什麼會複雜?
就如剝洋蔥一樣,你剝到最後才發現,是最裏層的裝飾出現了問題。
因此,儘量減少裝飾類的數量,以便降低系統的複雜度。
使用場景
- 需要擴展一個類的功能,或給一個類增加附加功能。
- 需要動態地給一個對象增加功能,這些功能可以再動態地撤銷。
- 需要爲一批的兄弟類進行改裝或加裝功能,當然是首選裝飾模式。