首页 > 其他分享 >桥接模式

桥接模式

时间:2023-09-07 18:11:06浏览次数:47  
标签:AbstractRoad __ run 桥接 模式 维度 new Road

桥接模式

1 作用

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


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

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

img

这个模型中有路和汽车两个变化维度,第一次继承是扩展路的维度、第二次继承是扩展汽车的维度,两个维度是一个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;
}

输出:

img

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

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

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

img

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

2 实现方式

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

img

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

img

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

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;
}

输出:

img

标签:AbstractRoad,__,run,桥接,模式,维度,new,Road
From: https://www.cnblogs.com/yuandonghua/p/17685738.html

相关文章

  • 韬客时代卷轴模式系统开发介绍和部分核心源码
    韬客时代是一种卷轴模式系统。什么是卷轴模式呢?新用户注册,先送你一部分积分,该积分用于兑换一个初始任务,俗称卷轴!卷轴模式的赚钱的原理是,你用积分兑换初级任务包,完成卷轴任务之后,你可以获得更多的积分,然后复投,达到一定数量后可以兑换更高级的任务包,任务包越高级每次获得的积分也就越......
  • kafka复习:(24)consume-transform-produce模式
    packagecom.cisdi.dsp.modules.metaAnalysis.rest.kafka2023;importorg.apache.kafka.clients.consumer.*;importorg.apache.kafka.clients.producer.KafkaProducer;importorg.apache.kafka.clients.producer.ProducerConfig;importorg.apache.kafka.clients.produc......
  • 区域LIS应用平台 云技术的SaaS模式
    在医疗机构内部,院内实验室主要负责本院临床科室的检验,院内LIS系统必须满足实验室日常的标本处理入库、仪器联机、检验结果处理、报告打印、报告发布、检验信息统计、检验信息报告发布、标本流程、外部医疗机构检验报告调阅等工作。 在医疗机构间,一方面在区域卫生信息平台上构建区......
  • 一文搞定,PO设计模式详解
    PO模式:全称:pageobjece,分层机制,让不同层去做不同类型的事情,让代码结构清晰,增加复⽤性。PO模式的优势:1)效率⾼:同理,PO模式的逻辑层⽅法有具体定义,情况和元素发⽣变化⼀样修改逻辑层,业务层不变。这样看来结构简单清晰,舒服更符合⼈类习惯,普通⽅式就是继续堆case。2)复⽤多收益⼤:同样......
  • 从追MM谈Java的23种设计模式
    1、FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory.以下是引用片段:实例一:publicclassFactory{......
  • 12种微服务模式
    释放微服务的力量您是否正在努力构建高效、可扩展且有弹性的软件系统?作为软件开发人员或高级开发人员,您一定遇到过“微服务架构”一词。这种革命性的软件开发方法已被许多成功的科技巨头采用,例如Netflix、亚马逊和Spotify。但是,微服务到底是什么,你为什么要关心?微服务架构是一种软......
  • 行为型设计模式-备忘录 Memento
    简介允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态,该状态保存在对象之外,这样就可以不破坏原有对象的封装性了。角色Originator原发器即需要被保存状态的类抽象Memento备忘录类定义备忘录基本接口可以看做成是快照Snapshot具体Memento备忘录类实......
  • 行为型设计模式-状态 State
    简介跟状态机密切相关。有限状态机FSM包含状态、事件、动作三个元素。当发生一个事件时,引发老状态变成新状态,并执行一个动作。状态和行为间一般是有限制的,如某些行为只能再某些状态下进行,某些状态只能触发某些行为。简单的状态间转换可使用ifelse。更有条理的可以用查表......
  • 行为型设计模式-策略 Strategy
    简介一组实现了同一个策略接口的策略,可以随时指定用哪一种策略完成业务。策略模式其实跟桥接模式很像,都是通过持有另一个对象,达到组合的效果。角色Context上下文可设置使用的Strategy抽象Strategy具体Strategy类图如图,Context使用setStrategy方法设置当前使......
  • 行为型设计模式-模板方法 Template Method
    简介父类抽象类定义大的处理流程,部分细节做成抽象方法,留给子类去实现。如Java的JUnit中,setUptearDown方法都是留给具体的测试用例来写,Servlet中service处理了一个请求的大部分工作,留下doGet和doPost给业务自定义处理。另外callback一般分两种方式:同步回调、异步回调,其中同步......