设计模式之禅【桥梁模式】

真刀实枪之桥梁模式

  • 从“I have Dream:”说起
    • 每个热都有自己的梦想,但只要不是空想,理想是要靠今天的拼搏来实现的
    • 现在假设字节的愿望可以自行设计与实现:那么来规划一下自己的事业吧
  • 富翁进行时
    1. 房地产比较火,先来个房地产公司
    2. 服装业与人们生活息息相关,再来个服装公司
    3. 不要贪多,先把这两个公司先经营好再说
  • 好了,富翁的公司已经规划好,现在来进行实现吧

    • 类图
    • 设计简单,但效益还不错!
    • 代码来实现

      • Corp

        package com.peng.ql;
        
        /**
         * @author kungfu~peng
         * @data 2017年12月6日
         * @description
         */
        public abstract class Corp {
            // 生产
            protected abstract void produce();
        
            // 销售
            protected abstract void shell();
        
            // 赚钱--模板方法
            public void makeMoney() {
                this.produce();
                this.shell();
            }
        }
        
      • HouseCorp

        package com.peng.ql;
        
        /**
         * @author kungfu~peng
         * @data 2017年12月6日
         * @description
         */
        public class HouseCorp extends Corp {
        
            @Override
            protected void produce() {
                System.out.println("房地产在盖房子~~");
            }
        
            @Override
            protected void shell() {
                System.out.println("房地产在销售房子~~~");
            }
        
            @Override
            public void makeMoney() {
                super.makeMoney();
                System.out.println("房地产公司大赚一笔~~~~~");
            }
        
        }
        
      • ClothesCorp

        package com.peng.ql;
        
        /**
         * @author kungfu~peng
         * @data 2017年12月6日
         * @description
         */
        public class ClothesCorp extends Corp {
        
            @Override
            protected void produce() {
                System.out.println("服装公司在生产衣服~~");
            }
        
            @Override
            protected void shell() {
                System.out.println("服装公司销售衣服~~~");
            }
        
            @Override
            public void makeMoney() {
                super.makeMoney();
                System.out.println("服装公司大赚一笔~~~~~");
            }
        
        }
        
      • Client

        package com.peng.ql;
        
        /**
         * @author kungfu~peng
         * @data 2017年12月6日
         * @description
         */
        public class Client {
        
            public static void main(String[] args) {
                System.out.println("富翁第一步:房地产");
                HouseCorp hc = new HouseCorp();
                hc.makeMoney();
                System.out.println("富翁第二步:服饰");
                ClothesCorp cc = new ClothesCorp();
                cc.makeMoney();
            }
        
        }
        
      • 执行结果

        富翁第一步:房地产
        房地产在盖房子~~
        房地产在销售房子~~~
        房地产公司大赚一笔~~~~~
        富翁第二步:服饰
        服装公司在生产衣服~~
        服装公司销售衣服~~~
        服装公司大赚一笔~~~~~
        
  • 富翁已经做成了,哈哈,代码的世界真的是美妙啊
  • 但是服装公司不是特别的挣钱啊,那么现在什么挣钱啊?苹果,对,但不是吃的那个苹果,是IPhone手机
  • 好了,设计思路已经有了,现在用勤劳的小手来实现一下吧!

    • 类图
    • 代码

      • Corp

        package com.peng.ql;
        
        /**
         * @author kungfu~peng
         * @data 2017年12月6日
         * @description
         */
        public abstract class Corp {
            // 生产
            protected abstract void produce();
        
            // 销售
            protected abstract void shell();
        
            // 赚钱--模板方法
            public void makeMoney() {
                this.produce();
                this.shell();
            }
        }
        
      • HouseCorp

        package com.peng.ql;
        
        /**
         * @author kungfu~peng
         * @data 2017年12月6日
         * @description
         */
        public class HouseCorp extends Corp {
        
            @Override
            protected void produce() {
                System.out.println("房地产在盖房子~~");
            }
        
            @Override
            protected void shell() {
                System.out.println("房地产在销售房子~~~");
            }
        
            @Override
            public void makeMoney() {
                super.makeMoney();
                System.out.println("房地产公司大赚一笔~~~~~");
            }
        
        }
        
      • IpadCorp

        package com.peng.ql;
        
        /**
         * @author kungfu~peng
         * @data 2017年12月6日
         * @description
         */
        public class IPadCorp extends Corp {
        
            @Override
            protected void produce() {
                System.out.println("生产Ipad~~");
            }
        
            @Override
            protected void shell() {
                System.out.println("销售Ipad~~~");
            }
        
            @Override
            public void makeMoney() {
                super.makeMoney();
                System.out.println("Ipad公司大赚一笔~~~~~");
            }
        
        }
        
      • Client

        package com.peng.ql;
        
        /**
         * @author kungfu~peng
         * @data 2017年12月6日
         * @description
         */
        public class Client {
        
            public static void main(String[] args) {
                System.out.println("富翁第一步:房地产");
                HouseCorp hc = new HouseCorp();
                hc.makeMoney();
                System.out.println("富翁第二步:Ipad");
                IPadCorp ic = new IPadCorp();
                ic.makeMoney();
            }
        
        }
        
      • 执行结果

        富翁第一步:房地产
        房地产在盖房子~~
        房地产在销售房子~~~
        房地产公司大赚一笔~~~~~
        富翁第二步:Ipad
        生产Ipad~~
        销售Ipad~~~
        Ipad公司大赚一笔~~~~~
        
  • 现在富翁做到了,但是有个问题:就是之前的服装公司去哪了,难道要新建一个公司就要抛弃原来的公司,再重新建立新的公司?有钱也不能这么任性!那该怎么做呢?

    • 废物利用,好主意,把公司的建筑留下,把产品改变一下就行了,然后生产新的产品,听起来还不错,不妨一试

      • 类图的设计
      • 看起来还不错,代码实现一下

        • Corp

          package ql2;
          
          /**
           * @author kungfu~peng
           * @data 2017年12月6日
           * @description
           */
          public abstract class Corp {
              // 产品对象
              private Product product;
          
              // 通过构造函数将产品传入
              public Corp(Product product) {
                  super();
                  this.product = product;
              }
          
              // 赚钱--模板方法
              public void makeMoney() {
                  // 生产产品
                  this.product.beProducted();
                  // 销售产品
                  this.product.beSelled();
              }
          
          }
          
        • HouseCorp

          package ql2;
          
          /**
           * @author kungfu~peng
           * @data 2017年12月6日
           * @description
           */
          public class HouseCorp extends Corp {
              public HouseCorp(Product product) {
                  super(product);
              }
          
              @Override
              public void makeMoney() {
                  super.makeMoney();
                  System.out.println("房地产公司大赚一笔~~~~~");
              }
          
          }
          
        • ShanZhaiCorp

          package ql2;
          
          /**
           * @author kungfu~peng
           * @data 2017年12月6日
           * @description
           */
          public class ShanZhaiCorp extends Corp {
              public ShanZhaiCorp(Product product) {
                  super(product);
              }
          
              @Override
              public void makeMoney() {
                  super.makeMoney();
                  System.out.println("山寨公司大赚一笔~~~~~");
              }
          
          }
          
        • Product

          package ql2;
          
          /**
           * @author kungfu~peng
           * @data 2017年12月6日
           * @description
           */
          public abstract class Product {
              // 生产产品
              public abstract void beProducted();
          
              // 销售产品
              public abstract void beSelled();
          
          }
          
        • House

          package ql2;
          
          /**
           * @author kungfu~peng
           * @data 2017年12月6日
           * @description
           */
          public class House extends Product {
              @Override
              public void beProducted() {
                  System.out.println("盖房中~~");
              }
          
              @Override
              public void beSelled() {
                  System.out.println("销售房屋中~~~");
              }
          
          }
          
        • Ipad

          package ql2;
          
          /**
           * @author kungfu~peng
           * @data 2017年12月6日
           * @description
           */
          public class Ipad extends Product {
              @Override
              public void beProducted() {
                  System.out.println("生产ipad中~~");
              }
          
              @Override
              public void beSelled() {
                  System.out.println("销售ipad中~~~");
              }
          }
          
        • Client

          package ql2;
          
          /**
           * @author kungfu~peng
           * @data 2017年12月6日
           * @description
           */
          public class Client {
              public static void main(String[] args) {
                  // 致富之路之房地产
                  Corp cp = new HouseCorp(new House());
                  cp.makeMoney();
                  // 致富之路中之山寨产品
                  cp = new ShanZhaiCorp(new Ipad());
                  cp.makeMoney();
              }
          }
          
        • 执行结果

          盖房中~~
          销售房屋中~~~
          房地产公司大赚一笔~~~~~
          生产ipad中~~
          销售ipad中~~~
          山寨公司大赚一笔~~~~~
          
  • 现在的改造基本完成,现在看下改造完后的好处
    1. 扩展公司:直接继承Corp,然后建立新的公司
    2. 扩展产品:直接继承Product,然后创建新的产品
    3. 高层模块只需要修改具体的实现类就可以了

桥梁模式的应用

  • Bridge Pattern
  • 也叫做桥接模式
  • Decouple an abstraction from its implementation so that the two can vary independenty.(将抽象的实现解耦,使得两者可以独立的变化)
  • 桥梁模式的重点在“解耦”上

桥梁模式的通用类图

  • 类图
  • 类图解释
    • Abstraction: 抽象化角色
    • RefineAbstraction:修正抽象化角色
    • Implementor:实现化角色
    • ConcreteImplementor具体实现化角色
  • 抽象角色引用实现角色---记住这个即可

通用代码

  • Abstraction

    package ql3;
    
    /**
     * @author kungfu~peng
     * @data 2017年12月6日
     * @description
     */
    public class Abstraction {
        // 定义实现化角色
        private Implementor imlementor;
    
        // 构造函数传入实现化角色
        public Abstraction(Implementor imlementor) {
            super();
            this.imlementor = imlementor;
        }
    
        // 自身的属性和方法
        public void request() {
            this.imlementor.doSomething();
        }
    
        // 获得实现化角色
        public Implementor getImlementor() {
            return imlementor;
        }
    
    }
    
  • RefineAbstraction

    package ql3;
    
    /**
     * @author kungfu~peng
     * @data 2017年12月6日
     * @description
     */
    public class RefinedAbstraction extends Abstraction {
        // 重写构造函数
        public RefinedAbstraction(Implementor imlementor) {
            super(imlementor);
        }
    
        // 修正父类的行为
        @Override
        public void request() {
            super.request();
            super.getImlementor().doAnything();
        }
    
    }
    
  • Implementor

    package ql3;
    
    /**
     * @author kungfu~peng
     * @data 2017年12月6日
     * @description
     */
    public abstract class Implementor {
        // 基本方法
        public abstract void doSomething();
    
        public abstract void doAnything();
    }
    
  • ConcreteImplementor1

    package ql3;
    
    /**
     * @author kungfu~peng
     * @data 2017年12月6日
     * @description
     */
    public class ConcreteImplementor1 extends Implementor {
    
        @Override
        public void doSomething() {
            // 业务逻辑处理
        }
    
        @Override
        public void doAnything() {
            // 业务逻辑处理
        }
    
    }
    
  • ConcreteImplementor2

    package ql3;
    
    /**
     * @author kungfu~peng
     * @data 2017年12月6日
     * @description
     */
    public class ConcreteImplementor2 extends Implementor {
    
        @Override
        public void doSomething() {
            // 业务逻辑处理
        }
    
        @Override
        public void doAnything() {
            // 业务逻辑处理
        }
    
    }
    

桥梁模式的应用

  • 桥梁模式的优点
    1. 抽象和实现分类
    2. 优秀的扩充能力
    3. 实现细节对客户透明

桥梁模式的使用场景

  • 不希望或不适用继承的场景
  • 接口或抽象类不稳定的场景
  • 重用性要求高的地方

最佳实践

  • 继承的优点有很多,可以把公共的方法或属性抽取,父类封装共性,子类实现特性,这是继承的基本功能,缺点有没有?有父类的方法,子类也必须有这个方法。这是不可选择的,会带来扩展性的问题--重写继承父类的方法,这样风险就太大了
  • 桥梁模式:描述类间弱关联关系,这样可以使用桥梁来搭相应的父子类
  • 不能说继承不好,它非常好,但是有缺点,可以扬长避短:对于不发生改变的,则可以通过继承来实现;若不能确定是否发生变化,则可以使用桥梁模式来解决,这才是一个完美的世界

声明

  • 摘自秦小波《设计模式之禅》第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、付费专栏及课程。

余额充值