1. 程式人生 > >六、裝飾模式

六、裝飾模式

一、基本概念

1、定義:動態地給一個物件新增一些額外的職責,就增加功能來說,裝飾模式比生成子類更為靈活。 2、作用:為已有功能動態地新增更多功能的一種方式。   3、何時使用裝飾模式:當系統需要新功能時,要求向舊的類中新增新的程式碼,這些新的程式碼通常裝飾了原有類的核心職責或主要行為。 4、優點:把類中裝飾功能從類中搬移去除,這樣可以簡化原有的類。    有效地把類的核心職責和裝飾功能區分開了,而且可以去除相關類中重複的裝飾邏輯。 5、特點:在主類中加入了新的欄位,新的方法和新的邏輯,從而增加了主類的複雜度,並讓這個類包裝它所需要裝飾的物件,因此,當需要執行特殊行為時,客戶程式碼就可以在執行時根據需要有選擇地,按順序地
使用裝飾功能包裝物件了
  6、裝飾模式結構圖 Component:定義一個物件介面(或者抽象類),可以給這些物件動態地新增職責; ConcreteComponent:定義了一個具體的物件,也可以給這個物件新增一些職責;——人 Decorator:裝飾抽象類,繼承了Component,從外類來擴充套件Component類的功能,但Component無需知道Decorator的存在。——衣物 ConcreteDecoratorA:具體的裝飾物件,起到給Component新增職責的功能~落到實處;——裙子  

 

7、簡化具體的實施過程
  • 如果ConcreteComponent只有一個,沒有Component,就可以讓Decorator直接繼承ConcreteComponent;
e.g 給一個人穿各種衣服
  • 如果ConcreteDecoratorA只有一種,就可以不要Decorator,直接讓ConcreteDecoratorA繼承Component。

 

二、示例:給小仙豬打扮一下

屬於簡化實施過程的第一種情況。

1、UML圖

 

2、程式碼

 Person類

 1 package thirdDecoration;
 2 
 3 // 相當於ConcreteCompement的person
 4 public class Person {
 5     private String name;
 6     public Person(){}
 7     public Person(String name){
 8         this.name=name;
 9     }
10      
11     public  void  show(){ //由於在Java中,普通類不能擁有抽象方法,且抽象方法無方法體,所以和書上C#的寫法不同
12         System.out.println("裝扮的"+this.name);
13     };
14 }

 

服飾類

 1 package thirdDecoration;
 2 
 3 public class Finery extends Person {
 4     protected Person compenent;
 5     public void Decorate(Person person){
 6         this.compenent=person;
 7     }
 8     public void show(){  //通過覆寫的方式增加子類的特性
 9         if (compenent!=null){
10             compenent.show();
11         }
12     }    
13 }

 

具體服飾類

1 package thirdDecoration;
2 
3 public class Tshirt extends Finery {
4     public void show(){
5         System.out.println("T恤");
6         super.show();
7     }
8 }
1 package thirdDecoration;
2 
3 public class Skirt extends Finery {
4     public void show(){
5         System.out.println("超短裙");
6         super.show();
7     }
8 }
1 package thirdDecoration;
2 
3 public class Dress extends Finery {
4     public void show(){
5         System.out.println("連衣裙");
6         super.show();
7     }
8 }

 

客戶端

 

 1 package thirdDecoration;
 2 
 3 public class DecorationTest {
 4 
 5     public static void main(String[] args) {
 6         Person person=new Person("小仙豬");//把物件找出來
 7         Tshirt tshirt=new Tshirt(); //把衣服準備好
 8         Skirt skirt=new Skirt(); //把衣服準備好
 9         
10         skirt.Decorate(person);//裙子穿上
11         tshirt.Decorate(skirt);//再把上衣穿上
12         tshirt.show();
13         
14         System.out.println("done!");
15     }
16 
17 }

 

分析:

  • 這部分和常理的理解有那麼一點不太一樣,因為我們正常是覺得,人還是那個人,但是穿了不同的衣服,人是主題,貫穿始終,但是這裡,人好像被包裹了一件衣服後,就不是這個人了。不過這只是一個例子而已。
  • 裝飾功能的裝飾順序很重要,示例中“穿衣服”是比較隨性的,但是工程中,例如加密資料和過濾詞彙都可以是資料持久化的裝飾功能,但是一定是先過濾詞彙然後再加密,否則會出問題的。