裝飾模式是在不使用繼承和不改變原類文件的狀況下,動態的擴展一個對象的功能。它是經過建立一個包裝對象,也就是裝飾來包裹真實的對象。html
這一個解釋,引自百度百科,咱們注意其中的幾點。java
1,不改變原類文件。設計模式
2,不使用繼承。函數
3,動態擴展。測試
在講優勢之間,咱們知道一個類的功能擴展咱們能夠經過繼承的方式重寫父類的方法來達到加強功能。那咱們來看下這兩種方式。this
(1) 類的繼承 ( 高耦合,會產生更多的子類,從而引發類的爆炸 )spa
(2) 對象組合即裝飾模式 ( 降耦,不會創造更多的子類 ) 動態的爲對象添加功能) 因此類應該對擴展開放,對修改關閉 。設計
那麼總結下裝飾者優勢:代理
1. 裝飾者模式與繼承關係的目的都是要擴展對象的功能,可是裝飾者能夠提供比繼承更多的靈活性。code
2. 經過使用不一樣的具體裝飾類以及這些裝飾類的排列組合,設計師能夠創造出不少不一樣行爲的組合。
主要來自一下四點(來自百度百科)
(1) 裝飾對象和真實對象有相同的接口。這樣客戶端對象就能以和真實對象相同的方式和裝飾對象交互。
(2) 裝飾對象包含一個真實對象的引用(reference)
(3) 裝飾對象接受全部來自客戶端的請求。它把這些請求轉發給真實的對象。
(4) 裝飾對象能夠在轉發這些請求之前或之後增長一些附加功能。這樣就確保了在運行時,不用修改給定對象的結構就能夠在外部增長附加的功能。
1) Component(抽象組件又叫被裝飾對象的基類)
定義一個對象接口,能夠給這些對象動態地添加職責。
2) ConcreteComponent(具體組件又叫具體被裝飾對象)
定義一個對象,能夠給這個對象添加一些職責。
3) Decorator(裝飾者抽象類)
維持一個指向Component實例的引用,並定義一個與Component接口一致的接口。
4)ConcreteDecorator(具體裝飾者)
具體的裝飾對象,給內部持有的具體被裝飾對象,增長具體的職責。
不得不說裝飾者模式和代理模式實現方式很是的像好比:
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】