设计模式之桥梁模式(C++)

1. 作业

桥梁模式完全是为了解决继承的缺点而设计的模式。继承的缺点是什么?即强侵入性,父类拥有的方法,子类必须照盘接收,如果只有这两层结构到没什么,假设是三层结构,子类下面还有子子类。突然有一天子类想重写父类的某个方法,但是子子类又想保持父类的方法实现,咋办?
意图:将抽象部分和实现部分分离,使他们都可以独立的变化。
继承恰恰就死抽象和实现耦合在一起的。关系够清楚了的吧。<\font >

2. UML类图

这里写图片描述
参与者:

  • Abstraction:定义抽象类接口,同时维护一个指向Impementor类型的指针。
  • RefinedAbstraction:实现扩充Abstraction定义的接口。
  • Impementor:定义实现类的接口,它的接口不必和Abstraction相同。一般来讲Impementor接口仅仅定义了基本操作,而Abstraction则定义了基于这些基本操作的较高层次操作。
  • Concrete Impementor:Impementor接口的具体实现。

3. 实现

  • 举例:相信80,90后都经历过这样一个变迁,小时候家里用的是白炽灯,开关是拉线开关,随着发展,节能灯取代白炽灯,按钮开关取代了拉线开关。开关和灯泡的关系可以看成是继承关系,因为开关可以看作是灯泡的一部分,灯泡完全拥有开关,如果真是使用继承设计,那么将无法应对开关和灯泡的变迁了。看看桥梁是怎么做的。
  • 代码:

#include <iostream>

using namespace std;

//实现化角色
//电灯
class Light
{
public:
    virtual void poweroOn() = 0;
    virtual void powerOff() = 0;
};

//具体实现化角色
//白炽灯
class FilamentLight :public Light
{
public:
    virtual void poweroOn()
    {
        cout << "白炽灯打开!" << endl;
    }
    virtual void powerOff()
    {
        cout << "白炽灯关闭!" << endl;
    }
};

//节能灯
class EfficientLight :public Light
{
public:
    virtual void poweroOn()
    {
        cout << "节能灯打开!" << endl;
    }
    virtual void powerOff() 
    {
        cout << "节能灯关闭!" << endl;
    }
};

//抽象角色定义
//开关
class Switch
{
public:
    Switch(Light *light) :m_pLight(light){}
    virtual void on() = 0;
    virtual void off() = 0;
    void setLight(Light *light){ m_pLight = light; }
protected:
    Light *m_pLight;
};


//修正抽象化角色
//拉线开关
class PullChainSwitch :public Switch
{
public:
    PullChainSwitch(Light *light) :Switch(light){}
    virtual void on()
    {
        cout << "拉线开关打开:";
        m_pLight->poweroOn();
    }
    virtual void off()
    {
        cout << "拉线开关关闭:";
        m_pLight->powerOff();
    }
};

//按钮开关
class ButtonSwitch :public Switch
{
public:
    ButtonSwitch(Light *light) :Switch(light){}
    virtual void on()
    {
        cout << "按钮开关打开:";
        m_pLight->poweroOn();
    }
    virtual void off()
    {
        cout << "按钮开关关闭:";
        m_pLight->powerOff();
    }
};



//场景
int main()
{ 
    //创建具体实现化角色
    Light *filamentLight = new FilamentLight;//白炽灯
    Light *efficientLight = new EfficientLight;//节能灯

    //创建具体抽象化角色
    Switch * pullChainSwitch = new PullChainSwitch(filamentLight);//白炽灯一般配拉线开关
    pullChainSwitch->on();

    //生活好了换了节能灯
    pullChainSwitch->setLight(efficientLight);
    pullChainSwitch->on();

    //生活好了又换了按钮开关了
    Switch * buttonSwitch = new ButtonSwitch(efficientLight);
    buttonSwitch->on();


    return 0;
}
结果:
拉线开关打开:白炽灯打开!
拉线开关打开:节能灯打开!
按钮开关打开:节能灯打开!
请按任意键继续. . .

4. 优缺点

  • 优点:
    1.抽象与实现分离,抽象部分。实现不受抽象的约束了。
    2.抽象和实现都非常好扩充。
    3.客户不用关心细节的实现,抽象层通过聚合关系进行了封装。
  • 缺点:
    1.桥接模式的使用会增加系统的理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计与编程。
    2.桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性,如何正确识别两个独立维度也需要一定的经验积累。

5. 使用场景

1.不希望使用继承的场景,不希望使用继承或因为多层继承导致系统类的个数急剧增加的系统
2.抽象接口不稳定的场景,接口有可能会改变。

6. 总结

桥梁模式是针对继承的不足提出了,一般当继承大于等于二层时,才考虑使用桥梁模式。此时才能显示出抽象变化的方便。

猜你喜欢

转载自blog.csdn.net/a369189453/article/details/81176196
今日推荐