裝飾器模式(Decorator Pattern)
是一種結構型設計模式,它允許你動態地給一個物件新增一些額外的職責(即增加其功能),就增加功能來說,裝飾器模式相比生成子類更為靈活。裝飾器模式是一種物件結構型模式,在其結構圖中含有一個作為抽象構件(Component)角色的介面和多個實現了該介面的抽象裝飾類(Decorator)角色。抽象裝飾類給原有業務類新增職責(方法或者屬性),並且含有指向抽象構件角色的引用。
模式結構
裝飾器模式主要包含以下角色:
- 抽象構件(Component)角色:它是具體構件和抽象裝飾類的共同父類,宣告瞭在具體構件中實現的業務方法,它的引入可以使客戶端以一致的方式處理未被裝飾的物件以及裝飾之後的物件,實現客戶端的透明操作。
- 具體構件(ConcreteComponent)角色:它是抽象構件角色的子類,用於定義具體的構件物件,實現了在抽象構件中宣告的方法,裝飾器可以為它增加額外的職責(方法)。
- 抽象裝飾(Decorator)角色:它也是抽象構件角色的子類,用於給具體構件增加職責,但是具體職責在抽象裝飾中並不實現。它維護一個指向抽象構件角色的引用,在抽象裝飾角色的子類中可以透過該引用來呼叫裝飾之前構件物件的方法,並透過其子類擴充套件該方法,以達到增加或增強功能的目的。
- 具體裝飾(ConcreteDecorator)角色:它是抽象裝飾角色的子類,負責向構件新增新的職責。每一個具體裝飾類都新增了一些額外的職責,同時它記住幷包含它的所裝飾的物件的引用。
工作原理
裝飾器模式的工作原理是動態地將責任附加到物件上。若要擴充套件一個物件的功能,裝飾器提供了一個比繼承更有彈性的替代方案。裝飾器模式透過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創造出很多不同行為的組合。
優點
- 透明性:客戶端可以一致地使用構件物件,而無需關心它是否被裝飾過,以及被裝飾了多少次。
- 靈活性:透過靈活使用不同的裝飾類以及這些裝飾類的排列組合,可以創造出很多不同行為的組合。
- 擴充套件性:如果需要新增新的功能,只需要增加一個新的具體裝飾類即可,無需修改原有程式碼。
缺點
- 多層裝飾比較複雜:如果多層裝飾的話,會導致系統設計中出現許多小類,這些類的區別只在於它們之間相互連線的方式有所不同。
- 可能會增加效能開銷:因為每次新增裝飾時,都需要建立一個新的裝飾物件,並儲存其引用,這可能會增加一些效能開銷。
示例程式碼(Java)
以下是一個簡單的裝飾器模式的示例程式碼:
java
// 抽象構件角色
interface Component {
void operation();
}
// 具體構件角色
class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("執行具體構件角色的操作");
}
}
// 抽象裝飾角色
abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
if (component != null) {
component.operation();
}
}
}
// 具體裝飾角色
class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
addedFunctionA();
}
public void addedFunctionA() {
System.out.println("為構件物件新增功能A");
}
}
// 另一個具體裝飾角色
class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
addedFunctionB();
}
public void addedFunctionB() {
System.out.println("為構件物件新增功能B");
}
}
// 客戶端程式碼
public class Client {
public static void main(String[] args) {
Component component = new ConcreteComponent();
// 使用裝飾器A
ConcreteDecoratorA decoratorA = new ConcreteDecoratorA(component);
decoratorA.operation();
// 使用裝飾器B
ConcreteDecoratorB decoratorB = new ConcreteDecoratorB(decoratorA);
decoratorB.operation();
}
}