7 結構型模式之 - 裝飾模式
裝飾模式介紹:裝飾模式也稱為包裝模式,是結構型模式之一,其使用一種對客戶端透明的方式來動態地擴展對象的功能,同時它也是繼承關系的一種替代方案之一。在現實生活中你也可以看見很多裝飾模式的例子,或者可以大膽地說裝飾模式無處不在,就拿人來說,人需要各式各樣的衣著,不管你穿著怎樣,但是,對於個人的本質來說是不變的,充其量只是在外面披上一層包裝而已,這就是裝飾模式,裝飾物也許各不相同但是裝飾的對象本質是不變的。
裝飾模式的定義:動態地給一個對象添加一些額外的職責,就增加功能來說,裝飾模式相比生成子類更加靈活
裝飾模式的使用場景:需要透明且動態地擴展類的功能時
我們通過一個生活中的例子來介紹裝飾模式的使用
人總是要穿衣服的,我們將人定義為一個抽象類,將其穿衣的行為定義為一個抽象方法。
1 /** 2 * 將人穿衣服定義成一個抽象方法 3 */ 4 public abstract class Person { 5 public abstract void dressed(); 6 }
該類也是我們要裝飾的原始對象,那麽具體裝飾對象是誰呢?
我們要實現一個具體的實現類
1 /** 2 * 具體裝飾對象的實現類 3 */ 4 public class Boy extends Person{ 5 @Override 6 public void dressed() { 7 System.out.println("穿了內衣和內褲");8 } 9 }
Boy類繼承於Person類,該類僅對Person中的dressed方法作了具體的實現,而Boy類則是我們所要裝飾的具體對象,現在需要一個裝飾者來裝飾我們的這個Boy對象,這裏定義一個PersonCloth類來表示人所穿著的衣服。
1 /** 2 * 裝飾者 3 */ 4 public abstract class PersonCloth extends Person{ 5 protected Person mPerson; 6 7 public PersonCloth(Person person){ 8 mPerson = person;9 } 10 11 @Override 12 public void dressed() { 13 mPerson.dressed(); 14 } 15 }
在PersonCloth類中我們保持了一個對Person類的引用,可以方便地調用具體被裝飾對象中的方法,這也是為什麽我們可以在不破壞原類層次結構的情況下為類增加一些功能,我們只需要在被裝飾者對象的相應方法的前或者後添加相應的功能邏輯就可以了,在裝飾物只有一個的情況下,可以不必聲明一個抽象類作為裝飾者抽象的提取,僅需定義一個普通的類表示裝飾者即可,這裏為了表明示例我們定義兩種衣服類型,一個類ExpensiveCloth表示高檔衣服。
1 /** 2 * 高檔衣服 3 */ 4 public class ExpensiveCloth extends PersonCloth{ 5 public ExpensiveCloth(Person person) { 6 super(person); 7 } 8 9 //穿了短袖 10 private void dressShirt(){ 11 System.out.println("穿了短袖"); 12 } 13 14 //穿了皮衣 15 private void dressLeather(){ 16 System.out.println("穿了皮衣"); 17 } 18 19 //穿了牛仔褲 20 private void dressJean(){ 21 System.out.println("穿了牛仔褲"); 22 } 23 24 @Override 25 public void dressed() { 26 super.dressed(); 27 dressShirt(); 28 dressLeather(); 29 dressJean(); 30 } 31 }
邏輯依舊很簡單,而另一個類CheapCloth則表示便宜的衣服
1 /** 2 * 便宜的衣服 3 */ 4 public class CheapCloth extends PersonCloth{ 5 public CheapCloth(Person person) { 6 super(person); 7 } 8 9 //穿短褲 10 public void dressShorts(){ 11 System.out.println("穿了短褲"); 12 } 13 14 @Override 15 public void dressed() { 16 super.dressed(); 17 dressShorts(); 18 } 19 }
這兩個類本質上並沒有區別,兩者都是為原本Boy類中的dressed方法提供功能擴展,不過這種擴展並非是直接修改原有的方法邏輯或者結構,更恰當地說,僅僅是在另一個類中將原有方法和新邏輯進行封裝和整合而已,最後我們來看看客戶類中的調用。
1 /** 2 * 測試類 3 */ 4 public class DecoratorTest { 5 6 public static void main(String[] args){ 7 test(); 8 } 9 10 public static void test(){ 11 12 //首先我們要有一個Person對象 13 Person person = new Boy(); 14 15 //然後為他穿上便宜的衣服 16 PersonCloth personCloth = new CheapCloth(person); 17 person.dressed(); 18 19 //然後為他穿上了貴的衣服 20 PersonCloth personCloth1 = new ExpensiveCloth(personCloth); 21 personCloth1.dressed(); 22 } 23 }
運行結果如下:
穿了內衣和內褲
穿了內衣和內褲
穿了短褲
穿了短袖
穿了皮衣
穿了牛仔褲
7 結構型模式之 - 裝飾模式