• 小侃设计模式(七)-桥接模式


    1.概述

    桥接模式(Bridge Pattern)是用于将抽象化与实现化进行分离,使两个层次可以独立改变。它是一种结构性设计模式,通过使用封装、聚合及继承等行为让不同得类承担不同得职责。它的主要特点是将抽象(Abstration)与行为实现(Implementation)分离开来,从而保持各部分得独立性以及应该它们的功能扩展。桥接模式的使用难度相对高一点,需要对场景有较高的抽象和理解。本文将分析桥接模式的原理及使用。

    2.概念及使用

    2.1 定义

    上述将抽象与实现部分进行分离,并不是说让抽象类与其派生类进行分离,实现指的是抽象类和它的派生类用来实现自己的对象。桥接模式中的脱耦,指的是一个软件系统的抽象化和实现化之间使用关联关系(组合或者聚合)而不是继承关系,从而使两者可以相对独立地变化。桥接模式的类图如下:
    在这里插入图片描述
    类图中各个类说明:

    1.Client:客户端调用者;
    2.抽象类(Abstraction):维护了Implementor,二者是聚合关系,Abstraction充当桥接类;
    3.实现类(AbstractionImpl):是Abstraction的具体实现子类,又叫扩充抽象类;
    4.行为接口(Implementor):定义行为实现类接口;
    5.行为实现类(ImplementorA、ImplementorB):都是Implementor的具体实现类;

    2.2 使用

    案例:去星巴克点咖啡,咖啡的种类有很多,按温度来分有常温、去冰、少冰,按咖啡的口味来分有美式拿铁、香草风味拿铁、燕麦拿铁等,还可以按照大杯、中杯、小杯的维度来进行区分;存在多个维度的变化,所以本文采用桥接模式来设计比较合适。
    本文按大小分为大、中、小三种杯型,按口味来区分,从这两个角度来进行分类。
    杯子大小是一个维度,定义为实现化角色,它有三个不同的具体实现化角色:大杯、中杯、小杯,通过getSize()方法可以获得杯子型号;咖啡类(Coffee)是另一个维度,定义为抽象化角色,它有两个扩展抽象化角色:美式拿铁、香草风味拿铁,包含了咖啡的种类,通过getType()方法可以选择相应的口味和容量。

    具体类图如下:

    在这里插入图片描述
    编码如下:

    public interface Size {
    
        String getSize();
    
    }
    
    public class Big implements Size {
        @Override
        public String getSize() {
            System.out.println("这是大杯");
            return "big";
        }
    }
    
    public class Middle implements Size {
        @Override
        public String getSize() {
            System.out.println("这是中杯");
            return "middle";
        }
    }
    
    public class Small implements Size {
    
        @Override
        public String getSize() {
            System.out.println("这是小杯");
            return "small";
        }
    
    }
    
    public abstract class Coffee {
    
        public Size size;
    
        public Coffee(Size size) {
            this.size = size;
        }
    
        public abstract String getSize();
    
        public abstract String getType();
    
    }
    
    
    public class AmericanCoffee extends Coffee {
    
        public AmericanCoffee(Size size) {
            super(size);
        }
    
        @Override
        public String getSize() {
            System.out.println("咖啡杯型为:" + size.getSize());
            return size.getSize();
        }
    
        @Override
        public String getType() {
            System.out.println("这是美式咖啡");
            return "AmericanCoffee";
        }
    }
    
    
    public class OatsCoffee extends Coffee {
        
        public OatsCoffee(Size size) {
            super(size);
        }
    
        @Override
        public String getSize() {
            System.out.println("咖啡杯型为:" + size.getSize());
            return size.getSize();
        }
    
        @Override
        public String getType() {
            System.out.println("这是燕麦咖啡");
            return "OatsCoffee";
        }
    }
    
    public class CoffeeManager {
    
        public static void main(String[] args) {
            Big big = new Big();
            AmericanCoffee americanCoffee = new AmericanCoffee(big);
            String type = americanCoffee.getType();
            String size = americanCoffee.getSize();
            System.out.println("这是:" + size + ":" + type + "咖啡");
    
            System.out.println("------------------------------------------");
    
            Middle middle = new Middle();
            OatsCoffee oatsCoffee = new OatsCoffee(middle);
            System.out.println("这是" + oatsCoffee.getSize() + ":" + oatsCoffee.getType() + "咖啡");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102

    运行结果如下:

    在这里插入图片描述
    桥接模式的主要使用场景如下:

    1.当一个类存在多个独立变化的维度(两个以上),且这两个维度还都需要进行扩展时;
    2.对于不希望通过继承或多层次继承而导致类个数剧增的系统;
    3.当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。

    3.小结

    1.桥接模式是结构型模式的一种,主要的目的还是为了解耦;
    2.策略模式的优势在于符合开闭原则、合成复用原则,其实现细节对用户透明;
    3.策略模式的难度在于需要对使用者的抽象能力要求较高。

    4.参考文献

    1.《大话设计模式》-程杰著
    2.《设计模式-可复用面向对象软件的基础》-Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides
    3.《可复用物联网Web3D框架的设计与实现》-程亮(知网)
    4.https://www.bilibili.com/video/BV1G4411c7N4-尚硅谷设计模式
    5.https://zhuanlan.zhihu.com/p/444297771

  • 相关阅读:
    【虚幻引擎】UE4/UE5 后期处理盒子(PostProcessVolume)
    一文带你看懂交直流一体化电源系统调试步骤
    c++中的String
    广州华锐互动VRAR | VR课件内容编辑器解决院校实践教学难题
    shell 重定向
    拼多多怎么引流商家?建议收藏的几个方法,拼多多引流脚本详细使用教学分享
    使用Flask-Restful后handle_error干扰无法正常捕获全局异常的解决
    Android 视频播放延时抖动那些事
    kubernetes(K8S)笔记
    数据结构和算法简介
  • 原文地址:https://blog.csdn.net/qq_33479841/article/details/127776970