美文网首页
桥接模式解读

桥接模式解读

作者: 谜00016 | 来源:发表于2019-02-27 14:13 被阅读3次

    提出需求

    • 初始需求
      小米手机有个MP3功能,可播放
    • 需求变更
      添加了一个华为手机,同样拥有MP3功能,可播放
    • 需求再变更
      两个手机品牌都需要再增加一个游戏的功能
    • 需求再再变更
      需要再增加若干个手机品牌以及若干个功能

    需求分析

    上述需求在真实案例中是很有可能发生的。代码需要根据需求的变更及时进行重构。我们先分析初始需求,这个需求很简单,可直接建一个小米手机类,添加MP3播放方法即可。

    当接收“需求变更”后,我们可能会想到建立一个手机抽象类,并添加MP3播放的抽象方法,然后建立小米和华为手机的类,继承这个手机抽象类并实现它里面的MP3播放方法。

    当接收“需求再变更”后,可能由于偷懒,不想重构,我们也只需要进行小小的改动也能满足需求。就是在手机抽象类中加一个游戏方法,并在两个实现类中进行实现。

    截止到目前,我们v1版本完成

    但是,客户是不会这么温柔的,在二期项目中,客户又提出了需求,目前由于业务未知,可能会增加若干手机品牌和若干功能。这下傻眼了,总不能一直去改抽象类和具体实现类吧。那么此时重构已成为必然。我们v2版本闪亮登场。

    代码实现

    V1版本

    • 结构图
    • 代码
      代码比较简单就不贴了

    V2版本(重点)

    • 代码结构
    • 代码分析

      因为需求是需要不定时新增不同的手机品牌和功能,那么我们可以考虑将手机品牌和手机功能分开,采用聚合的方式,来实现“对修改关闭,对扩展开放”的原则。最后的组织架构应该是这样的 将手机品牌和手机功能分开,手机品牌和手机功能通过聚合的方式进行关联。简单来说,手机品牌包含手机功能,但手机功能并不是手机品牌的一部分,他们之间是聚合的关系。
    • 代码实现
      AbstractFunc

    /**
     * @Author: ming.wang
     * @Date: 2019/2/27 10:08
     * @Description: 抽象功能类
     */
    public abstract class AbstractFunc {
        public abstract void run();
    }
    

    AbstractPhone

    /**
     * @Author: ming.wang
     * @Date: 2019/2/27 10:08
     * @Description: 手机品牌抽象类
     */
    public abstract class AbstractPhone {
    
       public AbstractFunc func;
    
       public AbstractFunc getFunc() {
          return func;
       }
    
       public void setFunc(AbstractFunc func) {
          this.func = func;
       }
    
       public abstract void run();
    
    }
    

    GameFunc

    /**
     * @Author: ming.wang
     * @Date: 2019/2/27 10:21
     * @Description:
     */
    public class GameFunc extends AbstractFunc {
        @Override
        public void run() {
            System.out.println("运行Game功能");
        }
    }
    
    

    Mp3Func

    /**
     * @Author: ming.wang
     * @Date: 2019/2/27 10:21
     * @Description:
     */
    public class Mp3Func extends AbstractFunc {
        @Override
        public void run() {
            System.out.println("运行MP3功能");
        }
    }
    
    

    XiaomiPhone

    /**
     * @Author: ming.wang
     * @Date: 2019/2/27 10:11
     * @Description:
     */
    public class XiaomiPhone extends AbstractPhone {
    
        @Override
        public void run() {
            func.run();
        }
    }
    
    

    HUAWEIPhone

    /**
     * @Author: ming.wang
     * @Date: 2019/2/27 10:11
     * @Description:
     */
    public class HUAWEIPhone extends AbstractPhone {
    
        @Override
        public void run() {
            func.run();
        }
    }
    

    Test

    /**
     * @Author: ming.wang
     * @Date: 2019/2/27 10:24
     * @Description:
     */
    public class Test {
        public static void main(String[] args) {
            AbstractPhone xiaomi=new XiaomiPhone();
            xiaomi.setFunc(new Mp3Func());
            xiaomi.run();
        }
    }
    
    

    通过我们的代码重构,我们现在如果接到一个需求“新增三星手机品牌,并且增加一个通讯录的功能”,那么我们只需要建立一个三星手机类,以及新增一个通讯录功能类就OK了,需要通讯录功能,就将他设置进去就好了。

    到目前为止,我们基本实现了客户需求,但是这样还是存在一个问题,一个手机品牌如何能同时集成多个功能呢?我们只需要小小的改动就可以了,V3版本如下:
    其他的不用变,只需要改AbstractPhone 和手机实现类
    AbstractPhone

    
    /**
     * @Author: ming.wang
     * @Date: 2019/2/27 10:08
     * @Description:
     */
    public abstract class AbstractPhone {
    
       public List<AbstractFunc> funcs=new ArrayList<>();
    
       public void addFunc(AbstractFunc func) {
          funcs.add(func);
       }
    
       public abstract void run();
    }
    

    XiaomiPhone

    /**
     * @Author: ming.wang
     * @Date: 2019/2/27 10:11
     * @Description:
     */
    public class XiaomiPhone extends AbstractPhone {
    
        @Override
        public void run() {
            System.out.println("小米手机:");
            funcs.stream().forEach(x -> x.run());
        }
    }
    

    Test

    
    /**
     * @Author: ming.wang
     * @Date: 2019/2/27 10:24
     * @Description:
     */
    public class Test {
        public static void main(String[] args) {
            AbstractPhone xiaomi=new XiaomiPhone();
            xiaomi.addFunc(new Mp3Func());
            xiaomi.addFunc(new GameFunc());
            xiaomi.run();
        }
    }
    

    个人理解

    桥接模式很好的践行了“开闭原则”。我们在考虑类之间的关系,优先考虑合成/聚合,尽量不要使用继承。因为继承是强耦合关系,当父类变化,子类也会受到影响。

    相关文章

      网友评论

          本文标题:桥接模式解读

          本文链接:https://www.haomeiwen.com/subject/wxlxuqtx.html