设计模式简单代码之Bridge模式(画圆系统设计篇)

/************************************************************************************************************/
* 作者:一雨田(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

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值