设计模式之禅之结构类PK【代理模式VS装饰模式】

设计模式之禅PK之结构类

结构类设计模式

  • 结构类模式:
    • 适配器模式
    • 桥梁模式
    • 组合模式
    • 装饰模式
    • 门面模式
    • 享元模式
    • 代理模式
  • 相同点:他们都是通过组合类或对象产生更大的结构以适应更高的层次的逻辑需求

【代理模式】VS【装饰模式】

  • 首先:
    • 装饰模式是代理模式的一个特殊应用,两者的共同特点是都具有相同的接口,不同点则是代理模式着重对代理过程的控制,而装饰模式则是对类的功能进行加强或减弱,它着重类的功能变化
  • 以例子驱动:找短跑运动员去跑步
    • 代理模式:找代理去说服
    • 装饰模式:加强运动员的跑步素质
  • 类图对比
代理模式装饰模式
  • 咦,怎么类图一样?别忘了装饰模式可是代理模式的一个特殊应用,这样一说就没什么神秘的了吧!

代码详细逻辑

  • 代理模式

    • IRunner

      package com.peng.pk_dl;
      
      /**
       * @author kungfu~peng
       * @data 2017年12月11日
       * @description
       */
      public interface IRunner {
          // 运动员的主要工作就是跑步
          public void run();
      }
      
    • Runner

      package com.peng.pk_dl;
      
      /**
       * @author kungfu~peng
       * @data 2017年12月11日
       * @description
       */
      public class Runner implements IRunner {
      
          @Override
          public void run() {
              System.out.println("运动员跑步,动作很潇洒!");
          }
      
      }
      
    • RunnerAgent

      package com.peng.pk_dl;
      
      import java.util.Random;
      
      /**
       * @author kungfu~peng
       * @data 2017年12月11日
       * @description
       */
      public class RunnerAgent implements IRunner {
      
          // 真正的运动员
          private IRunner ir;
      
          // 构造函数传入真正的运动员
          public RunnerAgent(IRunner ir) {
              super();
              this.ir = ir;
          }
      
          @Override
          public void run() {
              if (new Random().nextBoolean()) {
                  System.out.println("代理人允许!");
                  this.ir.run();
              } else {
                  System.out.println("代理人不允许!");
              }
          }
      
      }
      
    • Client

      package com.peng.pk_dl;
      
      /**
       * @author kungfu~peng
       * @data 2017年12月11日
       * @description
       */
      public class Client {
          public static void main(String[] args) throws InterruptedException {
              // 定义一个运动员
              IRunner ir = new Runner();
              // 定义这个运动员的代理人
              RunnerAgent ra = new RunnerAgent(ir);
              // 询问代理人是否运动员是否可以跑步
              for (int i = 0; i < 10; i++) {
                  Thread.sleep(1000);
                  System.out.println("======您好:代理,运动员可以跑吗--第" + (i + 1) + "次询问=====");
                  ra.run();
              }
          }
      }
      
    • 执行结果(某一次的执行结果)

      ======您好:代理,运动员可以跑吗--第1次询问=====
      代理人不允许!
      ======您好:代理,运动员可以跑吗--第2次询问=====
      代理人不允许!
      ======您好:代理,运动员可以跑吗--第3次询问=====
      代理人不允许!
      ======您好:代理,运动员可以跑吗--第4次询问=====
      代理人允许!
      运动员跑步,动作很潇洒!
      ======您好:代理,运动员可以跑吗--第5次询问=====
      代理人允许!
      运动员跑步,动作很潇洒!
      ======您好:代理,运动员可以跑吗--第6次询问=====
      代理人不允许!
      ======您好:代理,运动员可以跑吗--第7次询问=====
      代理人允许!
      运动员跑步,动作很潇洒!
      ======您好:代理,运动员可以跑吗--第8次询问=====
      代理人允许!
      运动员跑步,动作很潇洒!
      ======您好:代理,运动员可以跑吗--第9次询问=====
      代理人不允许!
      ======您好:代理,运动员可以跑吗--第10次询问=====
      代理人允许!
      运动员跑步,动作很潇洒!
      
  • 装饰模式

    • IRunner

      package com.peng.pk_dl;
      
      /**
       * @author kungfu~peng
       * @data 2017年12月11日
       * @description
       */
      public interface IRunner {
          // 运动员的主要工作就是跑步
          public void run();
      }
      
    • Runner

      package com.peng.pk_dl;
      
      /**
       * @author kungfu~peng
       * @data 2017年12月11日
       * @description
       */
      public class Client {
          public static void main(String[] args) {
              // 定义一个运动员
              IRunner ir = new Runner();
              // 定义这个运动员的装饰者
              RunnerWithJet ra = new RunnerWithJet(ir);
              ra.run();
          }
      }
      
    • RunnerWithJet

      package com.peng.pk_dl;
      
      
      /**
       * @author kungfu~peng
       * @data 2017年12月11日
       * @description
       */
      public class RunnerWithJet implements IRunner {
      
          // 真正的运动员
          private IRunner ir;
      
          // 构造函数传入真正的运动员
          public RunnerWithJet(IRunner ir) {
              super();
              this.ir = ir;
          }
      
          @Override
          public void run() {
              System.out.println("增加动力装置------喷火~~~~");
              this.ir.run();
          }
      
      }
      
    • Client

      package com.peng.pk_dl;
      
      /**
       * @author kungfu~peng
       * @data 2017年12月11日
       * @description
       */
      public class Client {
          public static void main(String[] args) {
              // 定义一个运动员
              IRunner ir = new Runner();
              // 定义这个运动员的装饰者
              RunnerWithJet ra = new RunnerWithJet(ir);
              ra.run();
          }
      }
      
    • 执行结果

      增加动力装置------喷火~~~~
      运动员跑步,动作很潇洒!
      

最佳实践

 代理模式装饰模式
细微的差别把当前的行为和功能委托给其他对象执行,代理类负责接口限定,是否可以调用真实角色,以及是否对发送到真实角色的消息进行变形处理,他不对对象的功能做任何的处理,保证原汁原味的调用保证接口不变的情况下加强类的功能(也可以削弱功能),但不做准入条件判断和准入参数过滤,这不是装饰模式关心的
应用范围俯拾皆是比较拘谨(java.io.*中有大量的使用)
eg:new DataOutputStream(new FileOutputStream("text.txt"))

声明

  • 摘自秦小波《设计模式之禅》第2版;
  • 仅供学习,严禁商业用途;
  • 代码手写,没有经编译器编译,有个别错误,自行根据上下文改正;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乘风御浪云帆之上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值