1.簡介
裝飾模式指的是在不必改變原類文件和使用繼承的情況下,動態地擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。
2.特點
(1) 裝飾對象和真實對象有相同的接口。這樣客戶端對象就能以和真實對象相同的方式和裝飾對象交互。
(2) 裝飾對象包含一個真實對象的引用(reference)
(3) 裝飾對象接受所有來自客戶端的請求。它把這些請求轉發給真實的對象。
(4) 裝飾對象可以在轉發這些請求以前或以後增加一些附加功能。這樣就確保了在運行時,不用修改給定對象的結構就可以在外部增加附加的功能。在面向對象的設計中,通常是通過繼承來實現對給定類的功能擴展。
3.適用場景
1. 需要擴展一個類的功能,或給一個類添加附加職責。
2. 需要動態的給一個對象添加功能,這些功能可以再動態的撤銷。
3. 需要增加由一些基本功能的排列組合而產生的非常大量的功能,從而使繼承關係變的不現實。
4. 當不能採用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,爲支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因爲類定義被隱藏,或類定義不能用於生成子類。
4.UML類圖
角色構成:
抽象組件角色(Component):定義一個對象接口,以規範準備接受附加責任的對象,即可以給這些對象動態地添加職責。
具體組件角色(ConcreteComponent) :被裝飾者,定義一個將要被裝飾增加功能的類。可以給這個類的對象添加一些職責。
抽象裝飾器(Decorator):維持一個指向構件Component對象的實例,並定義一個與抽象組件角色Component接口一致的接口。
具體裝飾器角色(ConcreteDecorator):向組件添加職責。
5.實例代碼
//抽象構建角色
interface Component{
public void Operation();
}
//具體的構建角色
class ConcreteComponent implements Component{
//我做了一份水煮肉片
public void Operation() {
//完成相關的業務代碼
System.out.println("我做了一份水煮肉片");
}
}
//抽象裝飾器
class Decorator implements Component{
private Component component;
public Decorator(Component component) {
this.component=component;
}
public void Operation() {
//委託給構建
component.Operation();
}
}
//具體的裝飾角色A
class ConcreteDecoratorA extends Decorator{
public ConcreteDecoratorA(Component component) {
super(component);
}
public void Operation() {
super.Operation();
//添加你需要的職責,例如給水煮肉片撒上一些香菜
System.out.println("給水煮肉片撒上一些香菜");
}
}
//具體的裝飾角色B
class ConcreteDecoratorB extends Decorator{
public ConcreteDecoratorB(Component component) {
super(component);
}
public void Operation() {
super.Operation();
//添加你需要的職責,例如給水煮肉片撒上一些辣椒粉
System.out.println("給水煮肉片撒上一些辣椒粉");
}
}
public class Client{
public static void main(String[] args) {
Component component = new ConcreteComponent();
Decorator decorator;
decorator=new ConcreteDecoratorA(component);
decorator.Operation();
decorator=new ConcreteDecoratorB(component);
decorator.Operation();
}
}
6.優點
- 裝飾模式與繼承關係的目的都是要拓展對象的功能,但是裝飾模式可以提供比繼承更多的靈活性。裝飾模式允許系統動態決定“貼上”一個需要的“裝飾”,或者“除掉”一個不需要的“裝飾”。繼承關係則不同,繼承關係是靜態的,它在系統運行前就決定了。
- 通過不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創造出更多不同行爲的組合。
7.缺點
由於使用裝飾模式,可以比使用繼承關係需要較少數目的類。使用較少的類,當然使設計比較易於進行。但是,在另外一方面,使用裝飾模式會產生比使用繼承關係所產生的更多的對象。而更多的對象會使得查找錯誤更爲困難,特別是這些對象在看上去極爲相似的時候。