• 桥接模式


    参考:https://www.cnblogs.com/wenlong/p/5255671.html

    1、作用

           当类的模型有两个或多个维度的时候,如果两个变化维度用同一个类使用继承方式实现会变得很复杂(冗余代码很多),不易于维护和扩展(继承关系是一种强耦合关系),为了降低耦合关系,提高维护性和可扩展性,可以将两个变化维度的通过两个类(abstruction、implementor类)来实现,将两个类的关系为弱耦合的关联关系,这样就可以提高程序的扩展性和可维护性。

          拿汽车在路上行驶的来说。既有小汽车又有公共汽车,它们都不但能在市区中的公路上行驶,也能在高速公路上行驶。这你会发现,对于交通工具(汽车)有不同的类型,它们所行驶的环境(路)也有不同类型,在软件系统中就要适应两个方面(不同车型,不同道路)的变化,怎样实现才能应对这种变化呢?

    如果使用继承关系来实现,对应的UML图为如下:

     这个模型中有路和汽车两个变化维度,第一次继承是扩展路的维度、第二次继承是扩展汽车的维度,两个维度是一个cross的关系,加入有10种路,10种汽车就会要继承出10*10+10个类,数量是指数增长的,也就是说扩展性很差,并且扩展出来的代码会有很多冗余的代码。

    Road.h

    #include <iostream>
    
    
    #ifndef __ROAD__H__
    #define __ROAD__H__
    
    using namespace std;
    
    class Road {
        public:
            virtual void run() = 0;
    };
    
    
    class SpeedWay: public Road {
        public:
            void run() override {
                cout<<"run on the speed way"<<endl;
            }
    };
    
    
    class Street: public Road {
        public:
            void run() override {
                cout<<"run on the street"<<endl;
            }
    };
    
    class CarOnSpeedWay: public SpeedWay {
        public:
            void run() override {
                cout<<"Car run on the speed way"<<endl;
            }
    };
    
    class BusOnSpeedWay: public SpeedWay {
        public:
            void run() override {
                cout<<"Bus run on the speed way"<<endl;
            }
    };
    
    class CarOnStreet: public Street {
        public:
            void run() override {
                cout<<"Car run on the Street"<<endl;
            }
    };
    
    class BusOnStreet: public Street {
        public:
            void run() override {
                cout<<"Bus run on the Street"<<endl;
            }
    };
    
    #endif

    test.cc

    #include "Road.h"
    
    int main() {
        Road *carOnSpeedway = new CarOnSpeedWay;
        Road *busOnSpeedway = new BusOnSpeedWay;
        Road *carOnStreet    = new CarOnStreet;
        Road *busOnStreet    = new BusOnStreet;
    
        carOnSpeedway->run();
        busOnSpeedway->run();
        carOnStreet->run();
        busOnStreet->run();
    
    
        return 0;
    }

    输出:

    缺点:
         但是我们说这样的设计是脆弱的,仔细分析就可以发现,它还是存在很多问题,首先它在遵循开放-封闭原则的同时,违背了类的单一职责原则,即一个类只有一个引起它变化的原因,而这里引起变化的原因却有两个,即路类型的变化和汽车类型的变化;其次是重复代码会很多,不同的汽车在不同的路上行驶也会有一部分的代码是相同的;

    再次是类的结构过于复杂,继承关系太多,难于维护,最后最致命的一点是扩展性太差。如果变化沿着汽车的类型和不同的道路两个方向变化,我们会看到这个类的结构会迅速的变庞大。

    如果要增加一种路和车型,比如StateRoad和Moto,得到的UML图就是复杂很多。

     增加了2种类型,却增加了6个类,且类型越多时,往后扩展,增加的类越多。主要原因是两个变化维度进行了cross,如果把两个维度进行独立开来,分开扩展就能实现某一个维度增加一种类型,只增加一个类,cross的操作,由用户来把握,这就要使用桥接模式。

    2、实现方式

    将两个变化维度分为两个基类(abstraction,implementor类中来实现),则两个类的关系为关联关系,而不是继承关系。如何将两个类关联在一起由用户的需求来选择。

     同样是上面的车在路上的模型,将路定义为Abstraction类,车定位为Implementor类(也可以反过来)。对应的UML模型如下:

    这个结构很清晰,方便后续的扩展和维护,如果要添加一种新的类型,只需要添加一个类即可完成。

    3、C++代码

    Road.h

    #include <iostream>
    
    #ifndef __CAR__H__
    #define __CAR__H__
    
    using namespace std;
    
    class AbstractCar {
        public:
            virtual void run () = 0;
    };
    
    class Car:public AbstractCar {
        public:
            void run () override {
                cout<<"Car";
            }
    };
    
    class Bus:public AbstractCar {
        public:
            void run () override {
                cout<<"Bus";
            }
    };
    
    class Moto:public AbstractCar {
        public:
            void run () override {
                cout<<"Moto";
            }
    };
    
    #endif

    Car.h

    #include <iostream>
    #include "Car.h"
    
    #ifndef __ROAD__H__
    #define __ROAD__H__
    
    using namespace std;
    
    class AbstractRoad {
        public:
            AbstractRoad(AbstractCar *car):car(car){}
            virtual void run() = 0;
        protected:
            AbstractCar *car;  // 为了使用多态性,必须使用指针或者引用。
    };
    
    class SpeedWay: public AbstractRoad {
        public:
            SpeedWay(AbstractCar *car):AbstractRoad(car){} // 子类的构造函数调用父类的构造函数来初始父类的成员
            void run() {
                car->run();
                cout<<" run on the speed way"<<endl;
            }
    };
    
    class Street: public AbstractRoad {
        public:
            Street(AbstractCar *car):AbstractRoad(car){}
            void run() {
                car->run();
                cout<<" run on the street"<<endl;
            }
    };
    
    class StateRoad: public AbstractRoad {
        public:
            StateRoad(AbstractCar *car):AbstractRoad(car){}
            void run() {
                car->run();
                cout<<" run on the state road"<<endl;
            }
    };
    
    #endif

    test.cc

    #include "Car.h"
    #include "Road.h"
    
    int main() {
        // 用户选择两个变化维度的组合。
        AbstractRoad *carOnSpeedway     = new SpeedWay(new Car);
        AbstractRoad *busOnSpeedway     = new SpeedWay(new Bus);
        AbstractRoad *motoOnSpeedway    = new SpeedWay(new Moto);
        AbstractRoad *carOnStreet       = new Street(new Car);
        AbstractRoad *busOnStreet       = new Street(new Bus);
        AbstractRoad *motoOnStreet      = new Street(new Moto);
        AbstractRoad *carOnStateRoad    = new StateRoad(new Car);
        AbstractRoad *busOnStateRoad    = new StateRoad(new Bus);
        AbstractRoad *motoOnStateRoad   = new StateRoad(new Moto);
    
        carOnSpeedway     ->run();
        busOnSpeedway     ->run();
        motoOnSpeedway    ->run();
        carOnStreet       ->run();
        busOnStreet       ->run();
        motoOnStreet      ->run();
        carOnStateRoad    ->run();
        busOnStateRoad    ->run();
        motoOnStateRoad   ->run();
    
        return 0;
    }

    输出:

  • 相关阅读:
    python 并发编程 多线程 event
    python 并发编程 多线程 定时器
    python 并发编程 多线程 信号量
    linux top 查看CPU命令
    python 并发编程 多线程 GIL与多线程
    python 并发编程 多线程 死锁现象与递归锁
    python 并发编程 多线程 GIL与Lock
    python GIL全局解释器锁与互斥锁 目录
    python 并发编程 多线程 GIL全局解释器锁基本概念
    执行python程序 出现三部曲
  • 原文地址:https://www.cnblogs.com/yuandonghua/p/11836249.html
Copyright © 2020-2023  润新知