裝飾者模式
1、意圖: 動態地給一個對象添加一些額外的職責。就增加功能來說, Decorator模式相比生成子類更為靈活。該模式以對客 戶端透明的方式擴展對象的功能。
2、適用環境
(1)在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。
(2)處理那些可以撤消的職責。
(3)當不能采用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每一種組合將產生大量的 子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用於生成子類。
3、參與者
1.Component(被裝飾對象的基類)
定義一個對象接口,可以給這些對象動態地添加職責。
2.ConcreteComponent(具體被裝飾對象)
定義一個對象,可以給這個對象添加一些職責。
3.Decorator(裝飾者抽象類)
維持一個指向Component實例的引用,並定義一個與Component接口一致的接口。
4.ConcreteDecorator(具體裝飾者)
具體的裝飾對象,給內部持有的具體被裝飾對象,增加具體的職責。
4、類圖
5、涉及角色
(1)抽象組件:定義一個抽象接口,來規范准備附加功能的類
(2)具體組件:將要被附加功能的類,實現抽象構件角色接口
(3)抽象裝飾者:持有對具體構件角色的引用並定義與抽象構件角色一致的接口
(4)具體裝飾:實現抽象裝飾者角色,負責對具體構件添加額外功能。
6、代碼
Component
public interface Person { void eat(); }
ConcreteComponent
public class Man implements Person { public void eat() { System.out.println("男人在吃"); } }
Decorator
public abstract class Decorator implements Person { protected Person person; public void setPerson(Person person) { this.person = person; } public void eat() { person.eat(); } }
ConcreteDectrator
public class ManDecoratorA extends Decorator { public void eat() { super.eat(); reEat(); System.out.println("ManDecoratorA類"); } public void reEat() { System.out.println("再吃一頓飯"); } } public class ManDecoratorB extends Decorator { public void eat() { super.eat(); System.out.println("==============="); System.out.println("ManDecoratorB類"); } }
Test
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(md1); md2.eat(); } }
7、裝飾者模式小結:
OO原則:動態地將責任附加到對象上。想要擴展功能, 裝飾者提供有別於繼承的另一種選擇。
8、要點:
1、繼承屬於擴展形式之一,但不見得是達到彈性設計的最佳方案。
2、在我們的設計中,應該允許行為可以被擴展,而不須修改現有的代碼。
3、組合和委托可用於在運行時動態地加上新的行為。
4、除了繼承,裝飾者模式也可以讓我們擴展行為。
5、裝飾者模式意味着一群裝飾者類, 這些類用來包裝具體組件。
6、裝飾者類反映出被裝飾的組件類型(實際上,他們具有相同的類型,都經過接口或繼承實現)。
7、裝飾者可以在被裝飾者的行為前面與/或后面加上自己的行為,甚至將被裝飾者的行為整個取代掉,而達到特定的目的。
8、你可以有無數個裝飾者包裝一個組件。
9、 裝飾者一般對組建的客戶是透明的,除非客戶程序依賴於組件的具體類型。