• 桥接模式


    问题场景:

    现在的手机有很多不同的品牌,样式也各种各样,什么水滴屏,刘海屏,挖孔屏,什么华为,vivo,小米等等。如果我们基于继承关系来设计的话,你就会发现这个时候有点无从下手了。

    当然这个图的设计是不合理的,你也可以试着将不同的屏再抽象下,但是发现还是不是很合理,而且即使实现了要扩展的话很是麻烦。这个时候我们就可以引入桥接模式。

    桥接模式的主要特点就是把抽象化与行为实现解耦,使得二者可以独立变化。

    在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活,就像上述场景,手机厂家有多个,手机屏幕也是多元化的。

    比如上诉问题,我们这样来设计

    打电话的行为提取一个接口出来,手机提取一个抽象出来,在抽象(Phone)里面去聚合行为(Brand),这个过程就像搭了个桥把抽象与行为连接起来。当然这样也把抽象和行为分离开来了,可以独立扩展,如果我要新增一个折叠屏的,只需要在抽象这边加一个类就OK,如果需要扩展手机品牌,只需要在接口实现那边加个小米就可以了,二者可以独立变化,提高系统的灵活性。

    行为侧:

    接口:

    package com.nijunyang.designpatterns.bridge.api;
     
    /**
     * @author: create by nijunyang
     * @date:2019/9/22
     */
    public interface Brand {
        void call();
        void close();
    }

     接口实现:

    package com.nijunyang.designpatterns.bridge.impl;
     
    import com.nijunyang.designpatterns.bridge.api.Brand;
     
    /**
     * @author: create by nijunyang
     * @date:2019/9/22
     */
    public class HuaWei implements Brand {
        @Override
        public void call() {
            System.out.println("华为手机打电话");
        }
     
        @Override
        public void close() {
            System.out.println("华为手机关机");
        }
    }

     抽象:

    抽象类:

    package com.nijunyang.designpatterns.bridge.phone;
     
    import com.nijunyang.designpatterns.bridge.api.Brand;
     
    /**
     * @author: create by nijunyang
     * @date:2019/9/22
     */
    public abstract class Phone {
        private Brand brand;
     
        public Phone(Brand brand) {
            this.brand = brand;
        }
     
     
        public void call() {
            brand.call();
        }
     
     
        public void close() {
            brand.close();
        }
    }

     子类:

    package com.nijunyang.designpatterns.bridge.phone;
     
    import com.nijunyang.designpatterns.bridge.api.Brand;
     
    /**
     * @author: create by nijunyang
     * @date:2019/9/22
     */
    public class WaterDropScreePhone extends Phone {
     
        public WaterDropScreePhone(Brand brand) {
            super(brand);
        }
     
        @Override
        public void call() {
            System.out.print("这是水滴屏");
            super.call();
        }
     
        @Override
        public void close() {
            System.out.print("这是水滴屏");
            super.close();
        }
    }

     测试:

    package com.nijunyang.designpatterns.bridge;
     
    import com.nijunyang.designpatterns.bridge.impl.HuaWei;
    import com.nijunyang.designpatterns.bridge.phone.Phone;
    import com.nijunyang.designpatterns.bridge.phone.WaterDropScreePhone;
     
    /**
     * @author: create by nijunyang
     * @date:2019/9/22
     */
    public class Test {
     
        public static void main(String[] args)
        {
            Phone phone = new WaterDropScreePhone(new HuaWei());
            phone.call();
        }
    }

     

    使用桥接模式需要找到合适的抽象与行为进行分离,它可以替代使用继承出现的多层继承或者接口的多实现情况,降低系统的管理和维护成本。但是会增加系统的理解和设计难度。

    JDBC驱动就是一个桥接模式的应用,通过DriverManager去聚合Connection实现搭桥,DriverManager通过配置去看是mysql或者是oracle等。各种武功变化万千,为武功心法不变,桥接模式中,抽象不一定非得是抽象类,行为也不一定非要抽取一个接口出来,就像JDBC这个,心法是一样,打出来的招式却有些变化。还有银行转账也是一个场景,不同用户可以通过不同方式转账。用户:普通用户,黄金用户,白金用户...,转账方式:网银转账 ,柜台转账,ATM转账,第三方支付转账...

    转载自:https://www.cnblogs.com/nijunyang/p/11565760.html

  • 相关阅读:
    【Azure Developer】使用Azure PubSub服务示例代码时候遇见了.NET 6.0的代码转换问题
    【Azure 事件中心】适用Mirror Maker生产数据发送到Azure Event Hub出现发送一段时间后Timeout Exception: Expiring 18 record(s) for xxxxxxx: 79823 ms has passed since last append
    【Azure API 管理】 为APIM创建一个审批订阅申请的RBAC角色,最少的Action内容是什么呢?
    【Azure 应用服务】Azure App Service多实例中,出现某一个实例CPU居高不下的情况,如何重启单个实例呢?
    【Azure 存储服务】Java Azure Storage SDK V12使用Endpoint连接Blob Service遇见 The Azure Storage endpoint url is malformed
    【Azure 应用服务】App Service 在修改应用服务计划的页面中,为什么无法查看到同一个资源组下面的其他应用服务计划(App Service Plan)呢?
    【Azure 应用服务】App Service for Windows 环境中为Tomcat自定义4xx/5xx页面
    SpringBoot自动注入后,找不到BCryptPasswordEncoder类型的Bean
    docker容器部分命令
    国内服务器访问github解决方法
  • 原文地址:https://www.cnblogs.com/cnhk19/p/12850104.html
Copyright © 2020-2023  润新知