* 作者:一雨田(http://blog.csdn.net/dylgsy/)。本文可随便转贴,但请保留此信息
*
* Bridge模式:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
* 这句话真是很晦涩,我来解释一下。所谓的实现部分,你可以想象成一个功能库,这个库是用类来组织的,
* 并且实现了你需要的功能,而抽象部分就是使用这个库的类。
* 让他们独立变化的意思就是说,库增加或者使用库的代码改变都是在两边独立变化的,不影响另一边
* 就好像隔了个桥梁一样,如果你理解了,就会觉得BRIDGE这个名字改得真好。
* 好了,如果不明白也没关系,先看看下面的代码。应该能明白的
/************************************************************************************************************/
/************************************************************************************************************/
* 任务叙述:我们现在要实现一个画图系统,这个系统的需求暂时来说有以下几个:
* 1、画圆、画长方形。(先实现画这两个形状)
* 2、已经有两个画图库了,这些画图库中定义了我们需要的操作,我们没必要重新去实现了
* 3、我们的系统能够决定使用哪个的画图库中的操作
* 根据以上的需求,我们的代码设计如下(这里先不使用Bridge模式,以便对比) :
/************************************************************************************************************/
/**********************************************************************************************************/
* 注意,这里使用了个预编译宏 _BRIDGE_MODE 来隔开使用Bridge和不使用Bridge两块代码。可以以这个来做分界对比看
* 两部分的代码
/**********************************************************************************************************/
#include <stdio.h>
#include <iostream>
using namespace std;
// 把这里注释掉就是不使用Bridge模式的代码
#define _BRIDGE_MODE
// 画图库1
class CDrawLib1
{
public:
void DrawCircle()
{
cout << "画圆操作1" << endl;
}
void DrawRectangle()
{
cout << "画长方形操作1" << endl;
}
void DrawTriangle()
{
cout << "画三角形操作1" << endl;
}
};
// 画图库2
class CDrawLib2
{
public:
void DrawCircle()
{
cout << "画圆操作2" << endl;
}
void DrawRectangle()
{
cout << "画长方形操作2" << endl;
}
void DrawTriangle()
{
cout << "画三角形操作2" << endl;
}
};
// 只要声明 _BRIDGE_MODE 就可以在使用或者不使用Bridge模式间切换了
#ifndef _BRIDGE_MODE
// 看到形状,很容易想到经典的Shape抽象类,并定义一个Draw接口
// 这里1代表使用画图库1的画图操作
class CShape1
{
public:
virtual void Draw() = 0;
protected:
CDrawLib1 _drawLib;
};
// 画圆和画长方形,好,这里就派生出两个形状
class CCircle1: public CShape1
{
public:
// 实现Draw操作,使用画图库1
virtual void Draw()
{
// 使用画图库1
_drawLib.DrawCircle();
}
};
class CRectangle1: public CShape1
{
public:
// 实现Draw操作,但是要使用画图库1
virtual void Draw()
{
// 使用画图库1
_drawLib.DrawRectangle();
}
};
// 再定义使用画图库2的Shape
class CShape2
{
public:
virtual void Draw() = 0;
protected:
CDrawLib2 _drawLib;
};
// 画圆和画长方形,好,这里就派生出两个形状
class CCircle2: public CShape2
{
public:
// 实现Draw操作,使用画图库2
virtual void Draw()
{
// 使用画图库2
_drawLib.DrawCircle();
}
};
class CRectangle2: public CShape2
{
public:
// 实现Draw操作,但是要使用画图库2
virtual void Draw()
{
// 使用画图库2
_drawLib.DrawRectangle();
}
};
void Draw1(CShape1 &s)
{
s.Draw();
}
void Draw2(CShape2 &s)
{
s.Draw();
}
// 好了,我们开始使用上面的类来实现我们的画图系统
void main()
{
cout << "不使用Bridge模式" << endl;
// 我可以使用两种库
CCircle1 c1;
CCircle2 c2;
CRectangle1 r1;
CRectangle2 r2;
Draw1(c1);
Draw1(r1);
Draw2(c2);
Draw2(r2);
}
/************************************************************************************************************/
* 好的,上述的代码运行正常,如果不需要维护的话,我们就不用管它拉~~
* 但是,代码是一定要维护的,逃不过的宿命。
* 出现变化的地方可能是这样的:
* 1、出现了第三个库
* 2、画图系统需要画三角形
* 这个时候,我们再看看要完成这两个变化我们需要作的修改,就会发现,我要晕了
* (当一个程序员要晕的时候,也就是BUG要出现的时候了)
/************************************************************************************************************/
#else
/************************************************************************************************************/
* 好了,现在让我们使用Bridge模式来实现上面的系统
* Bridge模式最重要是把表示和实现分开
/************************************************************************************************************/
// 建立一个实现操作的类:CShapeImp
class CShapeImp
{
public:
virtual void DrawCircle() = 0;
virtual void DrawRectangle() = 0;
};
class CShapeImp1: public CShapeImp
{
public:
virtual void DrawCircle()
{
_dLib.DrawCircle();
}
virtual void DrawRectangle()
{
_dLib.DrawRectangle();
}
private:
CDrawLib1 _dLib;
};
class CShapeImp2: public CShapeImp
{
public:
virtual void DrawCircle()
{
_dLib.DrawCircle();
}
virtual void DrawRectangle()
{
_dLib.DrawRectangle();
}
private:
CDrawLib2 _dLib;
};
class CShape
{
public:
virtual void Draw() = 0;
protected:
CShapeImp *_sImp;
};
class CCircle: public CShape
{
public:
CCircle(CShapeImp *imp)
{
_sImp = imp;
}
virtual void Draw()
{
_sImp->DrawCircle();
}
};
class CRectangle: public CShape
{
public:
CRectangle(CShapeImp *imp)
{
_sImp = imp;
}
virtual void Draw()
{
_sImp->DrawRectangle();
}
};
// 好了,我们利用上面的类结构来实现我们的画图系统
void main()
{
cout << "使用Bridge模式" << endl;
CShapeImp1 sImp1;
CShapeImp2 sImp2;
// 使用画图库1
CCircle c1(&sImp1);
CRectangle r1(&sImp1);
c1.Draw();
r1.Draw();
// 使用画图库2
CCircle c2(&sImp2);
CRectangle r2(&sImp2);
c2.Draw();
r2.Draw();
}
/************************************************************************************************************/
* 好的,上述的代码运行正常,并且维护也方便了,回想一下上面的两个新需求:
* 1、出现了第三个库
* 2、画图系统需要画三角形
* 考虑一下,对于第一个需求,我们只需要再增加一个ShapeImp就可以了。
* 再看第二个需求,我们也是只需要派生一个CTriangle就可以了
* 可以看出来,变化不再造成混乱,只需要单独针对变化改动代码就行了。
* 也就是,变化被Bridge给分开了。
/************************************************************************************************************/
/************************************************************************************************************/
* 对于这个的模式学习,个人推荐自己写写代码,感受一下使用Bridge和不使用的前后差别,
* 应该也会很快搞定它的。
/************************************************************************************************************/
#endif