設計模式——代理模式與裝飾模式的異同

兩種模式的特色


裝飾模式:java

  在不改變接口的前提下,動態擴展對象的訪問。
  動態繼承,讓類具備在運行期改變行爲的能力。
  裝飾模式,突出的是運行期增長行爲,這和繼承是不一樣的,繼承是在編譯期增長行爲
  強調:加強設計模式

代理模式:ide

  在不改變接口的前提下,控制對象的訪問。
  1.從封裝的角度講,是爲了解決類與類之間相互調用而由此致使的耦合關係,能夠說是接口的另一個層引用。
    好比:在a類->b代理->c類這個關係中,c類的一切行爲都隱藏在b中。即調用者不知道要訪問的內容與代理了什麼對象。
  2.從複用的角度講,能夠解決不一樣類調用一個複雜類時,僅僅因較小的改變而致使整個複雜類新建一個類。
    好比:a類->c類1;b類->c類2。
    能夠變爲a類->ca代理類->c類;b類->cb代理類-c類。
  代理模式,是類之間的封裝和(某方面的)複用。
  強調:限制測試

舉個例子說明問題


  下面經過一個例子來講明二者的不一樣。當咱們衝咖啡的時候,首先你要拿咖啡粉衝好一杯咖啡,而後你能夠考慮是否加方this

  那麼咖啡這個東西就能夠經過糖或奶或者糖和奶,變成加糖的咖啡、加奶的咖啡、加糖加奶的咖啡。spa

  可是它仍是一杯咖啡,只是它的屬性進行了擴展。.net

  接下來分別經過裝飾模式與代理模式,模擬這個過程。設計

1.裝飾模式3d

  測試代碼:代理

 1 Cafe cafe = new ConcreteCafe();
 2  
 3 Cafe milkCafe = new MilkDecorator(cafe);
 4 milkCafe.getCafe();
 5 System.out.println("----------------------------------------");
 6 Cafe sugarCafe = new SugarDecorator(cafe);
 7 sugarCafe.getCafe();
 8 System.out.println("----------------------------------------");
 9 Cafe sugarMilkCafe = new MilkDecorator(new SugarDecorator(new ConcreteCafe()));
10 sugarMilkCafe.getCafe();
11 System.out.println("----------------------------------------");
12 Cafe milkSugarCafe = new SugarDecorator(new MilkDecorator(cafe));
13 milkSugarCafe.getCafe();
14 System.out.println("----------------------------------------");

  就像使用IO流同樣:

1 BufferedReader in1 = new BufferedReader(new InputStreamReader(new FileInputStream(file)));//字符流
2 DataInputStream in2 = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));//字節流
  // DataInputStream-從數據流讀取字節,並將它們裝換爲正確的基本類型值或字符串
  // BufferedInputStream-能夠經過減小讀寫次數來提升輸入和輸出的速度

  對類進行了功能的加強。

2.代理模式

  測試代碼:

1 Cafe cafe = new Proxy();
2 cafe.getCafe();

如今能夠很清楚的看到:

  1. 裝飾模式可讓使用者直觀的看到加強了哪些功能,而代理模式徹底限制了使用者。

  2. 對裝飾模式來講,裝飾者(Decorator)和被裝飾者(Cafe)都實現同一個 接口。

  3. 對代理模式來講,代理類(Proxy Class)和真實處理的類(Real Class)都實現同一個接口。

  4. 此外,不論咱們使用哪個模式,均可以很容易地在真實對象的方法前面或者後面加上自定義的方法。

裝飾模式與繼承的比較


  明顯的,裝飾模式能夠動態的擴展對象的行爲。

  好比某對象有30項行爲,可是在第一階段用到1-20行爲,第二階段用到11-30項行爲,因此這時候,就能夠只定義11-20的行爲。

  在第一階段運行時,能夠將1-10的行爲以「裝飾1」給加上

  到第二階段運行時,能夠將「裝飾1」去掉,將21-30的能以「裝飾2」給加上。

  可是繼承是在編譯期增長行爲。

裝飾模式的優缺點


優勢:

  1. 裝飾模式能夠提供比繼承更多地靈活性。
  2. 能夠經過一種動態的方式來擴展一個對象的功能,在運行時選擇不一樣的裝飾器,從而實現不一樣的行爲。
  3. 經過使用不一樣的具體裝飾類以及這些裝飾類的排列組合,能夠創造出不少不一樣行爲的組合。能夠使用多個具體裝飾類來裝飾同一對象,獲得功能更爲強大的對象。
  4. 具體構件類與具體裝飾類能夠獨立變化,用戶能夠根據須要增長新的具體構件類和具體裝飾類,在使用時再對其進行組合,原有代碼無須改變,符合「開閉原則」。

缺點:

  1. 會產生不少的小對象(具體裝飾類),增長了系統的複雜性。
  2. 這種比繼承更加靈活機動的特性,也同時意味着裝飾模式比繼承易於出錯,排錯也很困難,對於屢次裝飾的對象,調試時尋找錯誤可能須要逐級排查,較爲煩瑣。

 

參考博文:

UML類圖

修飾模式與代理模式的區別

設計模式之——裝飾模式與代理模式的區別

Java之美——設計模式

裝飾者模式

源碼:

裝飾者模式:

 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年6月23日 上午11:10:23
 5  */
 6 package cafe;
 7 
 8 /**
 9  * @author zhengbinMac
10  * 抽象構件角色
11  */
12 public interface Cafe {
13     
14     public void getCafe();
15     
16 }
Cafe.java
 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年6月23日 上午11:11:03
 5  */
 6 package cafe;
 7 
 8 /**
 9  * @author zhengbinMac
10  * 具體構件角色
11  */
12 public class ConcreteCafe implements Cafe{
13 
14     @Override
15     public void getCafe() {
16         System.out.println("上一杯原味咖啡!");
17     }
18     
19 }
ConcreteCafe.java
 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年6月23日 上午11:13:41
 5  */
 6 package cafe;
 7 
 8 /**
 9  * @author zhengbinMac
10  * 裝飾角色
11  */
12 public class Decorator implements Cafe{
13 
14     public Cafe cafe;
15     
16     public Decorator(Cafe cafe) {
17         this.cafe = cafe;
18     }
19 
20     @Override
21     public void getCafe() {
22         cafe.getCafe();
23     }
24     
25 }
Decorator.java
 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年6月23日 上午11:13:29
 5  */
 6 package cafe;
 7 
 8 /**
 9  * @author zhengbinMac
10  * 具體裝飾角色
11  */
12 public class MilkDecorator extends Decorator{
13 
14     public MilkDecorator(Cafe cafe) {
15         super(cafe);
16     }
17     
18     @Override
19     public void getCafe() {
20         super.getCafe();
21         this.addMilk();
22     }
23     
24     private void addMilk() {
25         System.out.println("加奶!");
26     }
27     
28 }
MilkDecorator.java
 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年6月23日 上午11:14:22
 5  */
 6 package cafe;
 7 
 8 /**
 9  * @author zhengbinMac
10  * 具體裝飾角色
11  */
12 public class SugarDecorator extends Decorator{
13 
14     public SugarDecorator(Cafe cafe) {
15         super(cafe);
16     }
17     
18     @Override
19     public void getCafe() {
20         super.getCafe();
21         this.addSugar();
22     }
23     
24     private void addSugar() {
25         System.out.println("加糖!");
26     }
27     
28 }
SugarDecorator.java
  1 /**
  2  * Copyright 2016 Zhengbin's Studio.
  3  * All right reserved.
  4  * 2016年6月23日 上午11:18:32
  5  */
  6 package cafe;
  7 
  8 import java.io.BufferedInputStream;
  9 import java.io.BufferedReader;
 10 import java.io.DataInputStream;
 11 import java.io.File;
 12 import java.io.FileInputStream;
 13 import java.io.IOException;
 14 import java.io.InputStream;
 15 import java.io.InputStreamReader;
 16 import java.util.Date;
 17 
 18 /**
 19  * @author zhengbinMac
 20  * 測試類
 21  */
 22 public class Test {
 23 
 24     public static void main(String[] args) throws IOException {
 25         Cafe cafe = new ConcreteCafe();
 26         
 27         Cafe milkCafe = new MilkDecorator(cafe);
 28         milkCafe.getCafe();
 29         System.out.println("----------------------------------------");
 30         Cafe sugarCafe = new SugarDecorator(cafe);
 31         sugarCafe.getCafe();
 32         System.out.println("----------------------------------------");
 33         Cafe sugarMilkCafe = new MilkDecorator(new SugarDecorator(new ConcreteCafe()));
 34         sugarMilkCafe.getCafe();
 35         System.out.println("----------------------------------------");
 36         Cafe milkSugarCafe = new SugarDecorator(new MilkDecorator(cafe));
 37         milkSugarCafe.getCafe();
 38         System.out.println("----------------------------------------");
 39         
 40         File file = new File("/Users/zhengbinMac/test.txt");
 41         
 42         FileInputStream in2 = new FileInputStream(file);
 43         byte[] tempByte = new byte[1024];
 44         int hasRead = 0;
 45         System.out.println("開始時間:" + new Date().getTime());
 46         while((hasRead = in2.read(tempByte)) > 0) {
 47             System.out.println(new String(tempByte,0,hasRead));
 48         }
 49         System.out.println("結束時間:" + new Date().getTime());
 50         in2.close();
 51         
 52         System.out.println("----------------------------------------");
 53         
 54         FileInputStream in4 = new FileInputStream(file);
 55         byte[] tempByte2 = new byte[(int)file.length()];
 56         System.out.println("開始時間:" + new Date().getTime());
 57         in4.read(tempByte2);
 58         System.out.println("結束時間:" + new Date().getTime());
 59         in4.close();
 60         System.out.println(new String(tempByte2));
 61         
 62         System.out.println("----------------------------------------");
 63         
 64 //        DataInputStream in3 = new DataInputStream(new FileInputStream(file));
 65 //        String s;
 66 //        System.out.println("開始時間:" + new Date().getTime());
 67 //        while((s=in3.readLine()) != null) {
 68 //            System.out.println(s);
 69 //        }
 70 //        System.out.println("結束時間:" + new Date().getTime());
 71 //        in3.close();
 72         
 73         System.out.println("----------------------------------------");
 74         
 75 //        DataInputStream in5 = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
 76 //        String s1;
 77 //        System.out.println("開始時間:" + new Date().getTime());
 78 //        while((s1 = in5.readLine()) != null) {
 79 //            System.out.println(s1);
 80 //        }
 81 //        System.out.println("結束時間:" + new Date().getTime());
 82 //        in5.close();
 83         
 84         System.out.println("----------------------------------------");
 85         
 86         BufferedReader in6 = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
 87         String s2;
 88         System.out.println("開始時間:" + new Date().getTime());
 89         while((s2 = in6.readLine()) != null) {
 90             System.out.println(s2);
 91         }
 92         System.out.println("結束時間:" + new Date().getTime());
 93         in6.close();
 94         
 95         System.out.println("----------------------------------------");
 96         
 97         
 98     }
 99     
100 }
Test.java

代理模式:

 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年6月26日 下午8:30:42
 5  */
 6 package cafe3;
 7 
 8 /**
 9  * @author zhengbinMac
10  *
11  */
12 public interface Cafe {
13     
14     public void getCafe();
15     
16 }
Cafe.java
 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年6月26日 下午8:32:08
 5  */
 6 package cafe3;
 7 
 8 /**
 9  * @author zhengbinMac
10  *
11  */
12 public class ConcreteCafe implements Cafe{
13 
14     @Override
15     public void getCafe() {
16         System.out.println("上一杯原味咖啡!");
17     }
18     
19 }
ConcreteCafe.java
 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年6月26日 下午8:33:05
 5  */
 6 package cafe3;
 7 
 8 /**
 9  * @author zhengbinMac
10  *
11  */
12 public class Proxy implements Cafe{
13 
14     private ConcreteCafe concreteCafe;
15     
16     public Proxy() {
17         this.concreteCafe = new ConcreteCafe();
18     }
19     
20     @Override
21     public void getCafe() {
22         concreteCafe.getCafe();
23         addMilk();
24         addSugar();
25     }
26     
27     private void addMilk() {
28         System.out.println("加奶!");
29     }
30     
31     private void addSugar() {
32         System.out.println("加糖!");
33     }
34 
35 }
Proxy.java
 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年6月26日 下午8:38:51
 5  */
 6 package cafe3;
 7 
 8 /**
 9  * @author zhengbinMac
10  *
11  */
12 public class Test {
13 
14     public static void main(String[] args) {
15         Cafe cafe = new Proxy();
16         cafe.getCafe();
17     }
18     
19 }
Test.java

繼承:

 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年6月23日 上午11:30:41
 5  */
 6 package cafe2;
 7 
 8 /**
 9  * @author zhengbinMac
10  *
11  */
12 public class Cafe {
13     
14     public void getCafe() {
15         System.out.println("來一杯原味咖啡!");
16     }
17     
18 }
Cafe.java
 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年6月23日 上午11:32:32
 5  */
 6 package cafe2;
 7 
 8 /**
 9  * @author zhengbinMac
10  *
11  */
12 public class MilkCafe extends Cafe{
13 
14     @Override
15     public void getCafe() {
16         super.getCafe();
17         this.addMilk();
18     }
19     
20     private void addMilk() {
21         System.out.println("加奶!");
22     }
23 }
MilkCafe.java
 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年6月23日 上午11:31:09
 5  */
 6 package cafe2;
 7 
 8 /**
 9  * @author zhengbinMac
10  *
11  */
12 public class SugarCafe extends Cafe{
13     
14     @Override
15     public void getCafe() {
16         super.getCafe();
17         this.addSugar();
18     }
19     
20     private void addSugar() {
21         System.out.println("加糖!");
22     }
23 }
SugarCafe.java
 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年6月26日 下午3:01:26
 5  */
 6 package cafe2;
 7 
 8 /**
 9  * @author zhengbinMac
10  *
11  */
12 public class SugarMilkCafe extends Cafe{
13     @Override
14     public void getCafe() {
15         super.getCafe();
16         this.addSugarAndMilk();
17     }
18     
19     private void addSugarAndMilk() {
20         System.out.println("加糖!");
21         System.out.println("加奶!");
22     }
23 }
SugarMilkCafe.java
 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年6月23日 上午11:33:22
 5  */
 6 package cafe2;
 7 
 8 /**
 9  * @author zhengbinMac
10  *
11  */
12 public class Test {
13 
14     public static void main(String[] args) {
15         Cafe milkCafe = new MilkCafe();
16         milkCafe.getCafe();
17         
18         Cafe sugarCafe = new SugarCafe();
19         sugarCafe.getCafe();
20         
21         Cafe sugarMilkCafe = new SugarMilkCafe();
22         sugarMilkCafe.getCafe();
23     }
24     
25 }
Test.java
相關文章
相關標籤/搜索