4.2 设计模式_桥接模式

桥接模式,就是将抽象部分与它的实现部分分离,使他们都可以独立地变化。

假设说有两台电脑(MAC和Lenovo),它们分别安装不同的操作系统(Linux和Windows)。

编写代码实现给电脑安装操作系统。

最简单的办法

首先定义一个操作系统类,定义如下,有LinuxOS类和WindowsOS类。

class OS {
public:
    virtual void Install() = 0;
};

class LinuxOS : public OS {
public:
    virtual void Install() { cout << "Install Linux OS" << endl; }
};

class WindowsOS : public OS {
public:
    virtual void Install() { cout << "Install WindowsOS OS" << endl; }
};

电脑类的定义如下,有MAC类和Lenovo类。

class Computer {
public:
    virtual void printInfo() = 0;
};

class MAC : public Computer {
public:
    virtual void printInfo() { cout << "This is MAC, "; }
};

class Lenovo : public Computer {
public:
    virtual void printInfo() { cout << "This is Lenovo, "; }
};

它们有四种组合:

  1. MAC + Linux;
  2. MAC + Windows;
  3. Lenovo + Linux;
  4. Lenovo + Windows;
class MACWithLinux : public MAC, public LinuxOS {
public:
    void InstallOS() { printInfo(); Install(); }
};

class MACWithWindows : public MAC, public WindowsOS {
public:
    void InstallOS() { printInfo(); Install(); }
};

class LenovoWithLinux : public Lenovo, public LinuxOS {
public:
    void InstallOS() { printInfo(); Install(); }
};

class LenovoWithWindows : public Lenovo, public WindowsOS {
public:
    void InstallOS() { printInfo(); Install(); }
};

在main函数中编写测试代码。

main函数

int main()
{
    MACWithLinux a;
    a.InstallOS();

    MACWithWindows b;
    b.InstallOS();

    LenovoWithLinux c;
    c.InstallOS();

    LenovoWithWindows d;
    d.InstallOS();

    return 0;
}

编译测试,分别实现了给MAC/Lenovo,安装Linux/Windows的功能。

桥接模式

使用上面的方法,如果有N台不同厂家的电脑,M种不同类型的操作系统,那么总共就会有M*N种组合,就要在代码里面定义M*N个派生类,这样维护起来太麻烦了。

是否有更好的方法呢?

答:有,使用桥接模式

上面的代码中,定义了一个电脑类,一个操作系统类。

我们在电脑类操作系统类中间建立一个连接(搭一个桥)。

电脑类里面定义一个指针指向操作系统类

首先修改操作系统类和它的派生类,它们的定义与之前相同,只是函数名有一些改变(Install改为InstallOS_impl)。

class OS {
public:
    virtual void InstallOS_impl() = 0;
};

class LinuxOS : public OS {
public:
    virtual void InstallOS_impl() { cout << "Install Linux OS" << endl; }
};

class WindowsOS : public OS {
public:
    virtual void InstallOS_impl() { cout << "Install WindowsOS OS" << endl; }
};

然后修改电脑类,在Computer类里面将需要的函数定义为虚函数。

Computer类

class Computer {
public:
    virtual void printInfo() = 0;
    virtual void InstallOS() = 0;
};

以MAC类为例,

  1. 在MAC类中添加一个指向OS类的指针impl,它是一个私有数据成员;
  2. 增加InstallOS函数,在InstallOS函数中调用对应OS类的InstallOS_impl函数,也就是安装系统的实现函数;

MAC类

class MAC : public Computer {
private:
    OS *impl;

public:
    MAC(OS *impl) { this->impl = impl; }

    virtual void printInfo() { cout << "This is MAC, "; }
    virtual void InstallOS() { printInfo(); impl->InstallOS_impl(); } 
};

Lenovo类的修改与MAC类相同。

Lenovo类

class Lenovo : public Computer {
private:
    OS *impl;
public:
    Lenovo(OS *impl) { this->impl = impl; }

    virtual void printInfo() { cout << "This is Lenovo, "; }
    virtual void InstallOS() { printInfo(); impl->InstallOS_impl(); } 
};

在main函数中编写测试代码。

  1. 分别创建两个操作系统对象os1和os2,分别代表LinuxOS和WindowsOS;
  2. 然后分别创建电脑类:
    如果是MAC,就使用new MAC;如果是Lenovo,就使用new Lenovo;
    根据传入的参数决定安装哪种操作系统。
int main()
{
    OS *os1 = new LinuxOS();
    OS *os2 = new WindowsOS();

    Computer *c1 = new MAC(os1);
    Computer *c2 = new MAC(os2);

    Computer *c3 = new Lenovo(os1);
    Computer *c4 = new Lenovo(os2);

    c1->InstallOS();
    c2->InstallOS();
    c3->InstallOS();
    c4->InstallOS();

    return 0;
}

编译测试,结果符合预期。

此时,如果再加上一个Unix操作系统,加上一个Dell电脑。

那么,代码只需要再加两个类,UnixOS类和Dell类。

UnixOS类

class UnixOS : public OS {
public:
    virtual void InstallOS_impl() { cout << "Install Unix OS" << endl; }
};

Dell类 

class Dell : public Computer {
private:
    OS *impl;
public:
    Lenovo(OS *impl) { this->impl = impl; }

    virtual void printInfo() { cout << "This is Dell, "; }
    virtual void InstallOS() { printInfo(); impl->InstallOS_impl(); } 
};

修改main函数。

  1. 创建一个Unix操作系统对象;
  2. 分别给MAC,Lenovo,Dell安装Unix;
  3. 给Dell分别安装MAC,Lenovo,Unix;

 

测试结果如下,结果符合预期。

如果没有使用桥接模式,新增一个操作系统,一个电脑,需要多定义(3*3 - 2*2 = )5个派生类。

但是使用桥接模式后,只需要多定义两个2派生类,而且使用和维护也都很简单。

总结

最后,总结一下修改。

我们将电脑类定义为了一个抽象类,它含有抽象部分——InstallOS函数。

将操作系统类定义为了一个实现类,它包含实现部分——InstallOS_impl函数。

它们之间通过一个指针impl建立了连接,抽象类会调用实现类中的实现函数InstallOS_impl,来实现操作系统的安装。

而电脑类中仅提供了一个抽象的接口InstallOS,它不负责实现具体的功能。

这样,以后不论实现类有做什么更改,只要接口不变抽象类都可以不做变动;同理,不论抽象类如何扩展,也不会影响到实现类

它们互不影响。

impl = implement(实现)

如果看到impl,基本可以确认使用了桥接模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值