zoukankan      html  css  js  c++  java
  • 设计模式——代理模式与装饰模式的异同

    两种模式的特点


    装饰模式:

      在不改变接口的前提下,动态扩展对象的访问。
      动态继承,让类具有在运行期改变行为的能力。
      装饰模式,突出的是运行期增加行为,这和继承是不同的,继承是在编译期增加行为
      强调:增强

    代理模式:

      在不改变接口的前提下,控制对象的访问。
      1.从封装的角度讲,是为了解决类与类之间相互调用而由此导致的耦合关系,可以说是接口的另外一个层引用。
        比如:在a类->b代理->c类这个关系中,c类的一切行为都隐藏在b中。即调用者不知道要访问的内容与代理了什么对象。
      2.从复用的角度讲,可以解决不同类调用一个复杂类时,仅仅因较小的改变而导致整个复杂类新建一个类。
        比如:a类->c类1;b类->c类2。
        可以变为a类->ca代理类->c类;b类->cb代理类-c类。
      代理模式,是类之间的封装和(某方面的)复用。
      强调:限制

    举个例子说明问题


      下面通过一个例子来说明两者的不同。当我们冲咖啡的时候,首先你要拿咖啡粉冲好一杯咖啡,然后你可以考虑是否加方

      那么咖啡这个东西就可以通过糖或奶或者糖和奶,变成加糖的咖啡、加奶的咖啡、加糖加奶的咖啡。

      但是它还是一杯咖啡,只是它的属性进行了扩展。

      接下来分别通过装饰模式与代理模式,模拟这个过程。

    1.装饰模式

      测试代码:

     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
  • 相关阅读:
    浏览器 窗口 scrollTop 的兼容性问题
    document.documentElement.scrollTop || document.body.scrollTop;
    javascript函数querySelector
    :before和:after的内幕以及伪类
    css伪类伪元素
    JavaScript 运动框架 Step by step
    js中style,currentStyle和getComputedStyle的区别
    js函数变量
    函数
    oracle语法练习
  • 原文地址:https://www.cnblogs.com/zhengbin/p/5618564.html
Copyright © 2011-2022 走看看