zoukankan      html  css  js  c++  java
  • 设计模式

    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
    ";
    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
    ";
    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++设计模式——桥接模式

  • 相关阅读:
    SVN的安装与配置
    nginx之location配置详解及案例
    查看三种MySQL字符集的方法(转)
    JAVA_OPTS设置
    vi/vim 添加或删除多行注释
    Linux 下查看字体
    linux 安装中文字体
    Linux 压缩某个文件夹命令
    Navicat Premium 12.1.16.0安装与激活
    Rsync + sersync 实时同步备份
  • 原文地址:https://www.cnblogs.com/y4247464/p/14260120.html
Copyright © 2011-2022 走看看