在沒必要改變原類文件和使用繼承的狀況下,動態地擴展一個對象的功能。它是經過建立一個包裝對象,也就是裝飾來包裹真實的對象。
java
package com.amosli.dp.structural.decorator; public abstract class Component { public abstract void operation(); } package com.amosli.dp.structural.decorator; public class ConcreteComponent extends Component { @Override public void operation() { System.out.println("concrete operation..."); } } package com.amosli.dp.structural.decorator; public class Decorator extends Component { private Component component; public Component getComponent() { return component; } public void setComponent(Component component) { this.component = component; } @Override public void operation() { component.operation(); } } package com.amosli.dp.structural.decorator; public class ConcreteDecoratorA extends Decorator{ private String addedStat; public String getAddedStat() { return addedStat; } public void setAddedStat(String addedStat) { this.addedStat = addedStat; } @Override public void operation() { super.operation(); addedStat="addedStat"; System.out.println("added stat.."); } } package com.amosli.dp.structural.decorator; public class ConcreteDecoratorB extends Decorator { @Override public void operation() { super.operation(); addBehavior(); } public void addBehavior(){ System.out.println("add behavior"); } } package com.amosli.dp.structural.decorator; public class Client { public static void main(String[] args) { Component component = new ConcreteComponent(); Decorator decorator = new ConcreteDecoratorA(); Decorator decoratorB = new ConcreteDecoratorB(); decorator.setComponent(component); decoratorB.setComponent(decorator); decoratorB.operation(); } }
裝飾者模式隱含的是經過一條條裝飾鏈去實現具體對象,每一條裝飾鏈都始於一個Componet對象,每一個裝飾者對象後面緊跟着另外一個裝飾者對象,而對象鏈終於ConcreteComponet對象。git
問題: 說裝飾者模式比用繼承會更富有彈性,在類圖中不是同樣用到了繼承了嗎?
github
說明:裝飾者和被裝飾者之間必須是同樣的類型,也就是要有共同的超類。在這裏應用繼承並非實現方法的複製,而是實現類型的匹配。由於裝飾者和被裝飾者是同一個類型,所以裝飾者能夠取代被裝飾者,這樣就使被裝飾者擁有了裝飾者獨有的行爲。根據裝飾者模式的理念,咱們能夠在任什麼時候候,實現新的裝飾者增長新的行爲。若是是用繼承,每當須要增長新的行爲時,就要修改原程序了。ide
一、 想透明而且動態地給對象增長新的職責的時候。this
二、 給對象增長的職責,在將來存在增長或減小可能。spa
三、 用繼承擴展功能不太現實的狀況下,應該考慮用組合的方式。設計
一、 經過組合而非繼承的方式,實現了動態擴展對象的功能的能力。code
二、 有效避免了使用繼承的方式擴展對象功能而帶來的靈活性差,子類無限制擴張的問題。component
三、 充分利用了繼承和組合的長處和短處,在靈活性和擴展性之間找到完美的平衡點。orm
四、 裝飾者和被裝飾者之間雖然都是同一類型,可是它們彼此是徹底獨立並能夠各自獨立任意改變的。
五、 遵照大部分GRASP原則和經常使用設計原則,高內聚、低偶合。
一、 裝飾鏈不能過長,不然會影響效率。
二、 由於全部對象都是繼承於Component,因此若是Component內部結構發生改變,則不可避免地影響全部子類(裝飾者和被裝飾者),也就是說,經過繼承創建的關係老是脆弱地,若是基類改變,勢必影響對象的內部,而經過組合(Decoator HAS A Component)創建的關係只會影響被裝飾對象的外部特徵。
三、只在必要的時候使用裝飾者模式,不然會提升程序的複雜性,增長系統維護難度。
本系列文章源碼地址,https://github.com/amosli/dp 歡迎Fork & Star !!