Loading...
Yo, what’s up! 这里是二楼。
用户头像
粉丝
关注
随笔
文章
评论
阅读

【设计模式】之桥接模式

定义

桥接模式(Bridge Pattern)定义:将抽象化与实现化分离,使得双方可以独立变化。

当然定义什么的通常都晦涩难懂,咱们还是借助例子来理解。

举例

还是举个例子吧。

假如说,有个图形(Graphics)接口,具有方法draw(),他有两个可以变化的维度,形状(Shape)和颜色(Color)。怎么实现呢?容易想到这样一种方式:先从Graphics类继承出矩形(Rectangle)、圆形(Circle)等形状子类,再给每个形状子类分别派生出红色矩形(RedRectangle)、绿色矩形(GreenRectangle)、红色圆形(RedCircle)和绿色圆形(GreenCircle)。

此时的类体系结构如下:

有什么问题?

不难发现,如果我们要新增加一个形状,例如三角形,我们就需要对应增加n个子类(其中n=颜色个数),来使三角形具有不同的颜色。同样,如果我们要增加一种颜色,例如黄色,那么就需要对应增加m个子类(其中m=形状个数),来使所有的形状都具有黄色这种颜色。

事实上,如果我们有m种形状,n种颜色,那么我们一共需要的类的个数为m*n。

这也太可怕了吧!人是喜欢偷懒的动物,谁也不想为了区区几个形状和颜色写这么多个类。而且随着形状和颜色的增加,类的个数的增长速度也会越来越快,造成类爆炸。那有没有一种办法,可以让我们不需要写那么多类呢?答案当然是有的!试试看用组合替代继承会怎样?

咱们还是从Graphics类派生出各个形状子类,但不同的是,这次改用组合来使形状具有不同颜色,这时的类体系结构如下:

看,采用组合替代继承之后,当我们需要增加一种形状的时候,我们是不是只需要多写一个类了,不用为每个颜色对应增加一个形状类。同样,需要增加一种颜色的时候,也只需要写一个类,不用让每个形状都具有这种颜色。如果我们有m种形状,n种颜色,那么我们就只需要m+n个类就可以了,是不是比m*n要少的多了。

那上面的例子中,每个部分都扮演着什么样的角色呢?

抽象化(Abstraction):如例子中的Graphics类。
扩展抽象化(Refined Abstraction):由抽象化类派生而来,通过组合关系调用实现化类的相应方法,如例子中的RectangleCircle等类。
实现化(Implementation):如例子中的Color类。
具体实现化(Concrete Implementation):如例子中的RedGreen等类。

事实上,这只是桥接模式的其中一个使用场景。

使用场景

  1. 需要在抽象化和实现化角色之间增加更多的灵活性。
  2. 不希望因为类继承导致类的个数急剧增加。
  3. 一个系统有两个或多个变化维度且都需要扩展。

优缺点

优点

  1. 将抽象和具体实现分离开来。
  2. 提高了系统的可扩展性,改变或增加其中一个变化维度,不需要对另一个变化维度进行修改。
  3. 对客户隐藏实现细节。

缺点

  1. 会增加理解难度。(这算缺点吗?)

代码

话不多说,直接上代码(假设已#include相应头文件并using namespace std;):

Graphics类:

class Graphics
{
protected:
    Color &color;
public:
    Graphics(Color &color) : color(color) { }

    virtual void draw() = 0;
}

Rectangle类:

class Rectangle : public Graphics
{
public:
    Rectangle(Color &color) : Graphics(color) { }

    void draw() override
    {
        color.paint("矩形");
    }
}

Circle类:

class Circle : public Graphics
{
public:
    Circle(Color &color) : Graphics(color) { }

    void draw() override
    {
        color.paint("圆形");
    }
}

Color类:

class Color
{
public:
    virtual void paint(string shape) = 0;
}

Red类:

class Red : public Color
{
public:
    void paint(string shape) override
    {
        cout << "绘制红色的" << shape << endl;
    }
}

Green类:

class Green : public Color
{
public:
    void paint(string shape) override
    {
        cout << "绘制绿色的" << shape << endl;
    }
}

main函数:

int main(int argc, char *argv[])
{
    Red red();
    Rectangle rectangle(red);
    rectangle.draw();
    return 0;
)
posted @ 2022-09-20 15:45  YVVT_Real  阅读(51)  评论(1编辑  收藏  举报