• 【设计模式】桥接模式(Bridge Pattern)


    桥接模式属于结构型模式,主要解决因业务增长时滥用继承而导致的**“类爆炸”问题。桥接模式将一个树型的整体继承结构替换为由抽象的类(抽象化角色)组成的抽象部分和由实现接口(实现化角色)与实现类(具体实现化角色)组成的实现部分**,再让较为抽象的类中持有实现接口的实例,以此作为桥梁来完成两个部分的通信。此时,通过将继承关系替换成关联关系实现了抽象类部分与实现类部分的分离与解耦,使得二者可以独立变化。


    桥接模式的介绍

    ​ 桥接模式通过将抽象部分与实现部分抽离,使二者的关系有继承转变为聚合关联关系,以此来减少耦合性,让二者能够独立变化与扩展。

    ​ 这里的抽象实现并不特指abstractimplements,更多是现实生活中所认知的事物。例如:相对一部折叠式的华为手机来说,手机这个类就显得抽象得多,所以可以把手机看做抽象部分,折叠式华为手机看做实现部分。

    ​ 使用桥接模式可以让抽象和实现不再在同一个继承层次结构中,而是按照事物的多维度变化分成多个部分,而每个部分也需要“子类化”,不论抽象部分还是实现部分,都应当具有自己的子类,以便各个部分的子类随意组合,从而获得多维度的组合对象。

    优点

    • 解除了抽象与实现部分绑定关系,使得二者可以按照不同的维度扩展变化
    • 具有优秀的扩展能力
    • 符合开闭原则

    缺点

    • 需要开发者正确识别出系统中两个独立变化的维度,这增加系统的设计和理解难度

    应用场景

    • 消息系统中,从业务类型维度看存在普通消息、延时消息、加急消息等,从发送方式维度看有邮件发送、短息发送、公众号消息发送、站内消息发送等,此时就可以使用桥接模式进行分离。

    类爆炸

    ​ 一个事物通常有多个维度,例如,图形从形状上可分为圆形、方形等形状,从颜色角度看有红色、蓝色等。如要把图形按继承的方法抽象成类,那么圆形、方形继承与图形,而圆形又有红色的圆、蓝色的圆等多个子类。

    image-20221123163144895

    此时我要增加一个三角形,那同时也得增加红色三角形和蓝色三角形,假如我还想再增加一个绿颜色,那么所有图形都得再增加一个绿色的子类。之后当图形和颜色越加越多时,那这个结构中的类就会成指数的增长,导致**“类爆炸”**。

    image-20221123165726792



    桥接模式的使用

    ​ 以上面的图形例子来讲,我找到了两个变化的维度,一个是图形会增加,一个是颜色会增加。那么按照桥接模式,可以将颜色这个实现部分抽离出来,实现一个颜色接口,并在图形类中加入一个颜色的实例,以此完成颜色与图形的搭桥连接。

    类图

    image-20221123183647886

    • 抽象化(Abstraction)角色:定义抽象类,作为抽象与实现的桥梁,维护一个实现化对象的引用。
    • 扩展抽象化(RefinedAbstraction)角色:是抽象类的子类,实现父类中的抽象方法,通过父类维护的实现化对象来调用实现类中的业务方法。
    • 实现化(Implementor)角色:这个角色给出实现化角色的接口,但不给出具体的实现。必须指出的是,这个接口不一定和抽象化角色的接口定义相同,实际上,这两个接口可以非常不一样。实现化角色应当只给出底层操作,而抽象化角色应当只给出基于底层操作的更高一层的操作。
    • 具体实现化(ConcreteImplementor)角色:实现化角色接口的具体实现。


    实现方法


    第一步,编写实现接口

    图形颜色

    package 设计模式.结构型模式.桥接模式;
    
    /**
     * 实现化角色,每个实现类都通过该接口与抽象化相连接
     */
    public interface 图形颜色 {
        String 上色();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    第二步,编写实现类

    红色

    package 设计模式.结构型模式.桥接模式;
    
    /**
     * 具体实现类
     */
    public class 红色 implements 图形颜色 {
        @Override
        public String 上色() {
            return "红色";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    蓝色

    package 设计模式.结构型模式.桥接模式;
    
    /**
     * 具体实现类
     */
    public class 蓝色 implements 图形颜色 {
        @Override
        public String 上色() {
            return "蓝色";
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    第三步,编写抽象部分的类

    图形

    package 设计模式.结构型模式.桥接模式;
    
    /**
     * 抽象化角色
     */
    public abstract class 图形 {
        // 维护一个实现化的对象
        protected 图形颜色 颜色;
    
        protected 图形(图形颜色 颜色){
            // 通过构造方法注入实现类过程就是桥接的过程
            this.颜色 = 颜色;
        }
    
        public abstract void 绘制();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    圆形

    package 设计模式.结构型模式.桥接模式;
    
    public class 圆形 extends 图形 {
    
        // 通过构造方法传递具体的实现类对象,由抽象类保存维护
        protected 圆形(图形颜色 颜色) {
            super(颜色);
        }
    
        @Override
        public void 绘制() {
            // 在此方法中调用实现类,进行多维组合
            System.out.println("绘制一个圆形,并开始上色:"+颜色.上色());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    方形

    package 设计模式.结构型模式.桥接模式;
    
    public class 方形 extends 图形 {
        // 通过构造方法传递具体的实现类对象,由抽象类保存维护
        protected 方形(图形颜色 颜色) {
            super(颜色);
        }
    
        @Override
        public void 绘制() {
            // 在此方法中调用实现类,进行多维组合
            System.out.println("绘制一个正方形,并且开始上色:"+颜色.上色());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    第四步,编写测试类测试

    测试类

    package 设计模式.结构型模式.桥接模式;
    
    public class 测试类 {
        public static void main(String[] args) {
            圆形 红色圆形 = new 圆形(new 红色());
            红色圆形.绘制();
            方形 蓝色方形 = new 方形(new 蓝色());
            蓝色方形.绘制();
            圆形 蓝色圆形 = new 圆形(new 蓝色());
            蓝色圆形.绘制();
            方形 红色方形 = new 方形(new 红色());
            红色方形.绘制();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    测试结果

    image-20221123190551553

  • 相关阅读:
    力扣之滑动窗口《循序渐进》(209.长度最小的子数组、904. 水果成篮)
    NVIDIA 第七届 SkyHackathon(一)环境配置
    操作系统的“冷板凳”要坐多久?万字长文解读16年开源老兵的坚持
    Sentinel服务熔断和降级
    vue3 + vite + less配置全局style变量
    【Vue五分钟】五分钟让你了解vue组件的层级关系
    Redis事务相关源码探究
    D2--FPGA SPI接口通信2022-08-03
    若依RuoYi-Vue分离版—免登录直接访问
    智慧工地安全施工实时监测系统解决方案
  • 原文地址:https://blog.csdn.net/weixin_45634261/article/details/128008780