您的位置:首页 > 其它

设计模式中结构型模式(二)桥接模式(Bridge)

2008-04-21 18:53 633 查看
图示:

























模式Bridge的结构与对象适配器类似,但是Bridge模式的出发点不同:Bridge目的是将接口
部分和实现部分分离,从而对它们可以较为容易也相对独立的加以改变。而Adapter则意味着
改变一个已有对象的接口。
以下一些情况使用Bridge模式:
1、你不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如这种情况可能是因为,在
程序运行时刻实现部分应可以被选择或者切换。
2、类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时Bridge模式使你可以对不同的抽象
接口和实现部分进行组合,并分别对它们进行扩充。
3、对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
4、C++中你想对客户完全隐藏抽象的实现部分。在C++中,类的表示在类接口中是可见的。



代码Application类与IconWindow为外部接口类,它们从BaseWindow继承,都有接口方法DrawContents(),但完成的任务不同,这里的不同体现在两点,一点是作为接口函数,可以实现不同的接口功能,另一点是可以调用不同的实现类来完成所要定制的功能。
从代码中看出,通过字符串的切换便可达到调用不同的实现类,完成不同的功能,而实现类无需任何的改变。同样,实现类的改变也同样不会影响这里的接口部分。
原书中(指的那本《设计模式》)所述用一个factory工厂类来完成类的定义,将自动找寻到子类并new出来这样的功能封装在factory中,可惜我按书中的方法始终没成功,因此稍做了一些变通,或许使得实现类与接口类有一点的耦合,以后有时间再仔细研究一下。

以下为示例代码




// Bridge.h: interface for the Bridge class.


//




/**//**//**///////////////////////////////////////////////////////////////////////




#if !defined(AFX_BRIDGE_H__C037F529_E449_4786_8DEE_D8293BF666D5__INCLUDED_)


#define AFX_BRIDGE_H__C037F529_E449_4786_8DEE_D8293BF666D5__INCLUDED_




#if _MSC_VER > 1000


#pragma once


#endif // _MSC_VER > 1000




#include "BasicClass.h"


const MAX_PATH =250;


class View;


class WindowImp;




//Window的操作由WindowImp的接口定义。


//那么一个窗口怎样得到正确的WindowI子类的实例呢?在本例我们假设Window类具有


//职责,它的GetWindowImp操作负责从一个抽象工厂得到正确的实例,这个抽象工厂封


//装了所有窗口系统的细节。


class BaseWindow




...{


public:




BaseWindow()...{ _imp = 0; }


void SetClassName(const char* classname);


const char* GetClassNameA();






//requests handled by window




virtual void DrawContents()...{};






virtual void Open()...{}


protected:


WindowImp* GetWindowImp();


private:


char _className[MAX_PATH];


WindowImp* _imp;


};






//Window维护一个对WindowImp的引用,WindowImp抽象类定义了一个对底层窗口系统的接口


class WindowImp




...{


public:


virtual void DeviceRect(Coord, Coord, Coord, Coord) = 0;


virtual void DeviceText(const char*, Coord, Coord) = 0;


virtual void DeviceBitmap(const char*, Coord, Coord) = 0;


//lots more functions for drawing on windows


protected:




WindowImp()...{}


};




//Window的子类定义了应用程序可能用到的不同类型蝗窗口,如应用窗口,图标,对话框临时


//窗口以及工具箱的移动面板等。


//例如ApplicationWindow类将实现DrawContents 操作以绘制它所存储的View实例:


class ApplicationWindow: public BaseWindow




...{


public:


//


virtual void DrawContents();


};






//IconWindow中存储了它所显示的图标对应的位图名


//并且实现DrawContents操作将这个位图绘制在窗口上。


class IconWindow: public BaseWindow




...{


public:


//


virtual void DrawContents();


private:


const char* _bitmapName;


};






//具体的WindowImp子类可支持不同的窗口系统, XWindowImp子类支持XWindow窗口系统:


class XWindowImp: public WindowImp




...{


public:




XWindowImp()...{}




virtual void DeviceRect(Coord, Coord, Coord, Coord);


virtual void DeviceText(const char*, Coord, Coord) ;


virtual void DeviceBitmap(const char*, Coord, Coord);


//remainder of public interface


private:


//lots of X Window system-specific state, including:


// Display*_dpy;


// Drawable _winid;// window id;


// GC _gc;//window graphic context


};




//对于Presentation Manager(PM),


//我们定义PMWindowImp类


class PMWindowImp: public WindowImp




...{


public:




PMWindowImp()...{}


virtual void DeviceRect(Coord, Coord, Coord, Coord);


virtual void DeviceText(const char*, Coord, Coord) ;


virtual void DeviceBitmap(const char*, Coord, Coord);




//remainder of public interface


private:


//lots of PM window system-specific atate, including


//HPS _hps;


};






class WindowSystemFactory




...{


private:


static WindowSystemFactory* _instance;


public:


static WindowSystemFactory* Instance();


WindowImp* MakeWindowImp(const char* className);


};


#endif // !defined(AFX_BRIDGE_H__C037F529_E449_4786_8DEE_D8293BF666D5__INCLUDED_)














// Bridge.cpp: implementation of the Bridge class.


//




/**//**//**///////////////////////////////////////////////////////////////////////




#include "stdafx.h"


#include "Bridge.h"




#include <string.h>


#include <tchar.h>


#include <wtypes.h>




#include <string>


using std::string;




#define max(a,b) (((a) > (b)) ? (a) : (b))


#define min(a,b) (((a) < (b)) ? (a) : (b))


#define abs(a) ((a) < 0) ? (-(a)) : (a)




/**//**//**///////////////////////////////////////////////////////////////////////


// Construction/Destruction




/**//**//**///////////////////////////////////////////////////////////////////////




//////////////////////////////////////////////////////////////////////


// Construction/Destruction




/**//**//**///////////////////////////////////////////////////////////////////////




void BaseWindow::SetClassName(const char* classname)




...{


strcpy(_className, classname);


}




const char* BaseWindow::GetClassNameA()




...{


return _className;


}




WindowImp* BaseWindow::GetWindowImp()




...{


const char* className = GetClassNameA();


if(_imp == 0)




...{


_imp = WindowSystemFactory::Instance()->MakeWindowImp(className);


}


return _imp;


}










void ApplicationWindow::DrawContents()




...{


SetClassName(_T("XWindowImp"));





WindowImp* imp = GetWindowImp();


if(imp != 0)




...{


imp->DeviceRect(0,0,0,0);


}


//GetView()->DrawOn(this);


}






void IconWindow::DrawContents()




...{


SetClassName(_T("PMWindowImp"));


WindowImp* imp = GetWindowImp();


if(imp != 0)




...{


imp->DeviceBitmap(_bitmapName, 0.0, 0.0);


}


}




void XWindowImp::DeviceRect(Coord x0, Coord y0, Coord x1, Coord y1)




...{


#pragma warning(disable: 4244)


int x = min(x0, x1);


int y = min(y0, y1);


int w = abs(x0 - x1);


int h = abs(y0 - y1);


printf("XWindowImp::DeviceRect ");





#pragma warning(disable: 4244)


// XDrawRectangele(_dpy, _winid, _gc, x, y, w, h);


}





void XWindowImp::DeviceText(const char*, Coord, Coord)




...{


printf("XWindowImp::Devicetext ");


}


void XWindowImp::DeviceBitmap(const char*, Coord, Coord)




...{


printf("XWindowImp::DeviceBitmap ");


}


















void PMWindowImp::DeviceRect(Coord x0, Coord y0, Coord x1, Coord y1)




...{


#pragma warning (disable: 4244)


Coord left = min(x0, x1);


Coord right = max(x0, x1);


Coord bottom = min(y0, y1);


Coord top = max(y0, y1);




POINTL point[4];




point[0].x = left; point[0].y = top;


point[1].x = right; point[1].y = top;


point[2].x = right; point[2].y = bottom;


point[3].x = left; point[3].y = bottom;


printf("PMWindowmp::DeviceRect ");


// if(


// (GpiBeginPath(_hps, 1L) == false)


// || (GpiSetCurrentPosition(_hps, &point[3]) == false)


// || (GpiPolyLine(_hps, 4L, point) == GPI_ERROR)


// || (GpiEndPath(_hps) == false)


// )


// {


// //report error


// }


// else


// {


// GpistrokePath(_hps, 1L, 0L);


// }


}







void PMWindowImp::DeviceText(const char*, Coord, Coord)




...{


printf("PMWindowImp::Devicetext ");


}


void PMWindowImp::DeviceBitmap(const char*, Coord, Coord)




...{


printf("PMWindowImp::DeviceBitmap ");


}






/**//**//**///////////////////////////////////////////////////////////////////////////


WindowSystemFactory* WindowSystemFactory::_instance = NULL;


WindowSystemFactory* WindowSystemFactory::Instance()




...{


if(_instance == NULL)




...{


_instance = new WindowSystemFactory;


}


return _instance;


}




WindowImp* WindowSystemFactory::MakeWindowImp(const char* className)




...{


WindowImp* imp = NULL;




string strclassName = className;


if(strclassName == _T("PMWindowImp"))


imp = new PMWindowImp;


if(strclassName == _T("XWindowImp"))


imp = new XWindowImp;




return imp;


}










// testBridge.cpp : Defines the entry point for the console application.


//




#include "stdafx.h"




#include "Bridge.h"


int main(int argc, char* argv[])




...{


printf("Hello World! ");




ApplicationWindow apw;


IconWindow icw;




apw.DrawContents();


icw.DrawContents();






return 0;


}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: