Bridge桥模式也属于”的单一职责“模式中的典型模式。
问题描述:
我们绘制图形时,图形可以有不同形状以及不同颜色,比如圆形可以是红的,绿的,方形可以是红的绿的,如果用代码来描绘这些类,会有如下:

 1 class Shape{
2 };
3 class Rectangle : public Shape{
4 };
5 class Circle : public Shape{
6 };
7 class Color{
8 };
9 class Red : public Color{
10 };
11 class Blue : public Color{
12 };
13 class RedRectangle : public Red{
14 };
15 class BlueRectangle : public Blue{
16 };

每增加一种图形或者颜色,新增的类就会成倍得增长。而且CRedRectangle继承于颜色,似乎也不太合理,CRedRectangle和CRed之间不是一种is-a的关系。下面通过桥模式改善它?

定义

将抽象部分(业务功能)与实现部分(平台实现)分离,使它们都可以独立地变化。 ——《设计模式》GoF

简单的说就是抽象对外提供的接口,对外隐瞒实现部分,在抽象中引用实现部分,从而实现抽象对实现部分的调用,而抽象中引用的实现部分可以在今后的开发中,切换为别的实现部分。

动机

  • 解决继承带来的问题
    对象的继承关系是在编译时就定义好的,无法在运行时改变从父类继承的实现。父类实现中的任何变化都必然会导致子类发生变化。比如上面的代码,Red类是Color抽象类的具体实现,RedRectangle从Red类中继承了红色属性,就和颜色的实现绑定在了一起,RedRectangle的颜色实现就难以修改或扩展。通过桥接模式把依赖具体实现,提升为依赖抽象,来完成对象和变化因素之间的低耦合,提高系统的可维护性和扩展性。桥接模式的主要目的是将一个对象的变化与其它变化隔离开,让彼此之间的耦合度最低。
  • 合成/聚合复用原则
    聚合表示一种弱的‘拥有’关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分;合成则是一种强的‘拥有’关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。
    绘制矩形、圆形、椭圆、正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色、绿色、蓝色等,此时至少有如下两种设计方案:
    方案一:为每一种形状都提供一套颜色版本

    方案二:根据实际需要对形状和颜色进行组合

    明显方案二采用聚合的方式可以减少很多类的数量。

UML类图

Abstraction类定义了抽象类的接口,并且维护一个指向Implementor实现类的指针;

RefineAbstraction类扩充了Abstraction类的接口;

Implementor类定义了实现类的接口,这个接口不一定要与Abstraction的接口完全一致;实际上,这两个接口可以完全不同;

ConcreteImplementor类实现了Implementor定义的接口。

代码实现

 1 #include <iostream>
2
3 using namespace std;
4
5 //具体实现的抽象
6 class Implementor {
7 public:
8 virtual void operatonImpl() = 0;
9 };
10
11 //具体实现
12 class ConcreteImplementor : public Implementor {
13 public:
14 void oerationImpl() { cout << "OperationImpl" << endl; }
15 };
16
17 class Abstruction {
18 public:
19 Abstruction(Implementor* pImpl) : m_pImpl(pImpl) {}
20 virtual void operation() = 0;
21
22 protected:
23 Implementor* m_pImpl;
24 };
25
26 //重新定义抽象
27 class RedfinedAbstraction : public Abstruction {
28 public:
29 RedfineAbstraction(Implementor* pImpl) : Abstruction(pImpl) {}
30 void operation() { m_pImpl->operatonImpl(); }
31 };
32
33 int main() {
34 Implementor* pImplObj = new ConcreteImplementor();
35 Abstruction* pAbsObj = new RedfineAbstraction(pImplObj);
36 pAbsObj->operation();
37 delete pImplObj;
38 pImplObj = nullptr;
39 delete pAbsObj;
40 pAbsObj = nullptr;
41 return 0;
42 }

使用桥模式重新实现形状与颜色的代码:

 1 #include <iostream>
2 #include <string>
3
4 using namespace std;
5
6 class Color {
7 public:
8 virtual string name() = 0;
9
10 protected:
11 string mName;
12 };
13
14 class Green : public Color {
15 public:
16 Green() { mName = "Green"; }
17 virtual ~Green() {}
18 virtual string name() { return mName; }
19 };
20
21 class Red : public Color {
22 public:
23 Red() { mName = "Red"; }
24 virtual ~Red() {}
25 virtual string name() { return mName; }
26 };
27
28 class Shape {
29 public:
30 Shape(Color* color) : mColor(color) {}
31 virtual void myShape() = 0;
32
33 protected:
34 Color* mColor;
35 };
36
37 class Rectangle : public Shape {
38 public:
39 Rectangle(Color* color) : Shape(color) {}
40 virtual void myShape() {
41 cout << "Rectangle has a " << mColor->name() << " color\n";
42 }
43 };
44
45 class Circle : public Shape {
46 public:
47 Circle(Color* color) : Shape(color) {}
48 virtual void myShape() {
49 cout << "Circle has a " << mColor->name() << " color\n";
50 }
51 };
52
53 int main() {
54 Color* red = new Red();
55 Color* green = new Green();
56
57 Shape* rectangle = new Rectangle(red);
58 rectangle->myShape();
59 Shape* circle = new Circle(green);
60 circle->myShape();
61
62 return 0;
63 }

桥模式的优点

分离抽象接口及其实现的部分

  • 桥接模式有点类似于多继承,但是多继承违背了类的单一职责原则(一个类只有一个变化的原因),复用性差,且多继承结构中类的个数庞大,桥接模式是比多继承方案更好的解决方案。
  • 桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原系统。
  • 实现细节对客户透明,可以对用户隐藏实现细节。

桥模式的缺点

  • 桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
  • 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围有局限性。

参考:

桥接模式(c++实现)

C++设计模式——桥接模式

设计模式 - Bridge 桥模式的更多相关文章

  1. c++ 设计模式7 (Bridge 桥模式)

    4.2 Bridge 桥模式 动机: 由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个变化的维度. 代码示例: 实现一个Messager,含有基本功能PlaySound,Connec ...

  2. C++设计模式-Bridge桥接模式

    作用:将抽象部份与它的实现部份分离,使它们都可以独立地变化. 将抽象(Abstraction)与实现(Implementation)分离,使得二者可以独立地变化. 桥接模式号称设计模式中最难理解的模式 ...

  3. 一天一个设计模式——Bridge桥接模式

    一.概念准备 在理解桥接模式之前,先要理解面向对象程序设计中的两个概念: 类的功能层次结构:假设现在有一个类Something,这个类有一些成员属性和成员方法,但是现有的功能不能满足要求,因此我们想扩 ...

  4. Bridge 桥模式

    之前一直以为桥是简单地沟通几个不同接口,使之能够按照一定流程工作.但重新查了一下解释,才有新解. 对于同一个产品的不同影响因子,如果使用继承的话,则这些影响因子则会按照M1*M2* ... Mn的数量 ...

  5. Java设计模式(6)桥模式(Bridge模式)

    Bridge定义:将抽象和行为划分开来,各自独立,但能动态的结合. 为什么使用桥模式 通常,当一个抽象类或接口有多个具体实现(concrete subclass),这些concrete之间关系可能有以 ...

  6. 设计模式的征途—8.桥接(Bridge)模式

    在现实生活中,我们常常会用到两种或多种类型的笔,比如毛笔和蜡笔.假设我们需要大.中.小三种类型的画笔来绘制12中不同的颜色,如果我们使用蜡笔,需要准备3*12=36支.但如果使用毛笔的话,只需要提供3 ...

  7. C#设计模式之八桥接模式(Bridge)【结构型】

    一.引言 今天我们要讲[结构型]设计模式的第二个模式,该模式是[桥接模式],也有叫[桥模式]的.大家第一次看到这个名称会想到什么呢?我第一次看到这个模式根据名称猜肯定是连接什么东西的.因为桥在我们现实 ...

  8. C#设计模式之七桥接模式(Bridge Pattern)【结构型】

    一.引言 今天我们要讲[结构型]设计模式的第二个模式,该模式是[桥接模式],也有叫[桥模式]的,英文名称:Bridge Pattern.大家第一次看到这个名称会想到什么呢?我第一次看到这个模式根据名称 ...

  9. 面向对象设计模式纵横谈:Bridge 桥接模式(笔记记录)

    桥接模式是一个比较难理解的设计模式,设计和分析的时候也不容易把握,咱们听听“李建忠”老师是怎么来讲的.我们还是从演变的角度来说问题,一步一步的来把问题说清楚.先谈谈“抽象”和“实现”的关系. 抽象与实 ...

随机推荐

  1. sqlmap --eval 用法

    今天查资料发现 sqlmap 有一个 --eval 的参数 --eval=EVALCODE Evaluate provided Python code before the request (e.g. ...

  2. (8)java Spring Cloud+Spring boot+mybatis企业快速开发架构之SpringCloud-Spring Cloud Eureka是什么?

    ​ Spring Cloud Eureka 是 Spring Cloud Netflix 微服务套件的一部分,基于 Netflix Eureka 做了二次封装,主要负责实现微服务架构中的服务治理功能. ...

  3. Centos下Yum安装PHP7.0

    默认的版本太低了,手动安装有一些麻烦,想采用Yum安装的可以使用下面的方案: 1.检查当前安装的PHP包 yum list installed | grep php 如果有安装的PHP包,先删除他们 ...

  4. 第一节:《线程安全和锁Synchronized概念》

    第一节:线程安全和锁Synchronized概念 一.进程与线程的概念 (1)在传统的操作系统中,程序并不能独立运行,作为资源分配和独立运行的基本单位都是进程. 在未配置 OS 的系统中,程序的执行方 ...

  5. php move_uploaded_file保存文件失败

    move_uploaded_file保存失败后找错,先使用了try catch,但是没输出信息,才知道该函数在php中是警告属于error,不属于exeption,因此不能通过简单的if(!...)处 ...

  6. java中避免集合死链调用

    目录 1. 前言 2. 场景 3. 环境 3.1 开发环境准备 3.2 数据准备 3.2.1 Mysql数据库表及数据 3.2.2 redis库数据 4. 解决方式 5.完整代码 5.1Model 5 ...

  7. Shell系列(19)- 正则表达式

    正则表达式与通配符 正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配.grep,awk,sed等命令可以支持正则表达式. 通配符用来匹配符号条件的文件名,通配符是完全匹配.ls,find,c ...

  8. ci框架 自定义配置方法

    系统自动在Application文件夹下生成的config.php文件,采用key-value关联数组的形式来存放配置项和值.为了使结构更清晰,手动新建另外一个配置文件myconfig.php,所采用 ...

  9. 鸿蒙内核源码分析(构建工具篇) | 顺瓜摸藤调试鸿蒙构建过程 | 百篇博客分析OpenHarmony源码 | v59.01

    百篇博客系列篇.本篇为: v59.xx 鸿蒙内核源码分析(构建工具篇) | 顺瓜摸藤调试鸿蒙构建过程 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿 ...

  10. 一篇文章搞定Selenium元素定位/封装/数据驱动

    小伙伴都知道,自动化最重的,又最"难"(因为实战中会碰到定位的各种坑)那就是定位元素.如果不熟练掌握定位,那只怕你比功能测式的小伙伴下班还会要晚!扎心了吧! Selenium常用定 ...