现在的位置: 首页 > 综合 > 正文

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

2017年12月07日 ⁄ 综合 ⁄ 共 7399字 ⁄ 字号 评论关闭

图示:

 

 

 

 

 

 

 

 

 

 

 

模式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.00.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;
}


 

 

 

 

 

抱歉!评论已关闭.