設計模式之裝飾者模式
一、概念
1、什么是裝飾者模式
裝飾模式是在不使用繼承和不改變原類文件的情況下,動態的擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。
這一個解釋,引自百度百科,我們注意其中的幾點。
1,不改變原類文件。
2,不使用繼承。
3,動態擴展。
2、裝飾模式的優點
在講優點之間,我們知道一個類的功能擴展我們可以通過繼承的方式重寫父類的方法來達到增強功能。那我們來看下這兩種方式。
(1) 類的繼承 ( 高耦合,會產生更多的子類,從而引起類的爆炸 )
(2) 對象組合即裝飾模式 ( 降耦,不會創造更多的子類 ) 動態的為對象添加功能) 所以類應該對擴展開放,對修改關閉 。
那么總結下裝飾者優點:
1. 裝飾者模式與繼承關系的目的都是要擴展對象的功能,但是裝飾者可以提供比繼承更多的靈活性。
2. 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創造出很多不同行為的組合。
3、裝飾者特點
主要來自一下四點(來自百度百科)
(1) 裝飾對象和真實對象有相同的接口。這樣客戶端對象就能以和真實對象相同的方式和裝飾對象交互。
(2) 裝飾對象包含一個真實對象的引用(reference)
(3) 裝飾對象接受所有來自客戶端的請求。它把這些請求轉發給真實的對象。
(4) 裝飾對象可以在轉發這些請求以前或以后增加一些附加功能。這樣就確保了在運行時,不用修改給定對象的結構就可以在外部增加附加的功能。
4、參與者
1) Component(抽象組件又叫被裝飾對象的基類)
定義一個對象接口,可以給這些對象動態地添加職責。
2) ConcreteComponent(具體組件又叫具體被裝飾對象)
定義一個對象,可以給這個對象添加一些職責。
3) Decorator(裝飾者抽象類)
維持一個指向Component實例的引用,並定義一個與Component接口一致的接口。
4)ConcreteDecorator(具體裝飾者)
具體的裝飾對象,給內部持有的具體被裝飾對象,增加具體的職責。
5、裝飾者代理模式的區別
不得不說裝飾者模式和代理模式實現方式非常的像比如:
1) 代理模式中代理類和被代理類都要實現統一接口,而裝飾者模式中被裝飾對象和裝飾者抽象類都要實現統一接口。
2)代理模式中被代理類中構造函數中需要傳入一個代理類對象,而裝飾者模式中裝飾者抽象類中也許傳入具體裝飾對象。
3)它們都可以對方法在不使用繼承的情況下對方法進行功能加強。
但是要注意一點區別:代理類中被代理類中僅一個被代理類(沒有代理接口,和代理實現類之分),而裝飾着模式中有裝飾者抽象類和具體裝飾者。
那這有什么用呢?其實很關鍵。
那就說明裝飾者模式可以做到層層增加功能,比如IO流使用的裝飾者模式。代理模式可以用於增加特殊的功能。 但它很難支持多層嵌套。
看下面圖片后,有助於更加理解。
裝飾者模式

代理模式

二、案例說明
下面舉一個案例。
抽象組件
public interface Person { void eat(); }
具體組件
public class Man implements Person { public void eat() { System.out.println("男人在吃"); } }
抽象裝飾者
public abstract class Decorator implements Person { protected Person person; public void setPerson(Person person) { this.person = person; } public void eat() { person.eat(); } }
具體裝飾者
//具體裝飾者A public class ManDecoratorA extends Decorator { public void eat() { super.eat(); reEat(); System.out.println("ManDecoratorA類"); } public void reEat() { System.out.println("再吃一頓飯"); } } //具體裝飾B public class ManDecoratorB extends Decorator { public void eat() { super.eat(); System.out.println("==============="); System.out.println("ManDecoratorB類"); } }
測試類
public class Test { public static void main(String[] args) { Man man = new Man(); ManDecoratorA md1 = new ManDecoratorA(); ManDecoratorB md2 = new ManDecoratorB(); md1.setPerson(man); md2.setPerson(man); md2.eat(); } }
總結
OO原則:動態地將責任附加到對象上。想要擴展功能, 裝飾者提供有別於繼承的另一種選擇。
參考
想太多,做太少,中間的落差就是煩惱。想沒有煩惱,要么別想,要么多做。中校【6】
