设计模式(7) 桥接模式(BRIDGE)(二)

2014-11-24 02:55:13 · 作者: · 浏览: 1
dow { public: Window(View*contents); // requests handled by window virtual void DrawContents(); virtual void Open(); virtual void Close(); virtual void Iconify(); virtual void Deiconify(); // requests forwarded to implementation virtual void SetOrigin(const Points& at); virtual void SetExtent(const Points& extent); virtual void Raise(); virtual void Lower(); virtual void DrawLine(const Point&, const Point&); virtual void DrawRect(const Point&, const Point&); virtual void DrawPolygon(const Point[], int n); virtual void DrawText(const char*, const Points&); protected: WindowImp* GetWindowImp(); View* GetView(); private: WindowImp* _imp; View* _contents; };
Window维护一个对WindowImp的引用,WindowImp抽象类定义了一个对底层窗口系统的接口
class WindowImp
{
public:
    virtual void ImpTop() = 0;
    virtual void ImpBottom() = 0;
    virtual void ImpSetExtent(const Point&) = 0 ;
    virtual void ImpSetOrigin(const Point&) = 0;

    virtual void DeviceRect(Coord, Coord, Coord, Coord) = 0;
    virtual void DeviceText(const char*, Coord, Coord) = 0;
    virtual void DeviceBitmap(const char*, Cood, Coord) = 0;
    // lots more functions for drawing on windows...
protected:
    WindowImp();
};

Window的子类定义了应用差您工序可能用到的不同类型的窗口,如应用窗口,图标,对话框临时窗口,以及工具箱的移动面板等。 如ApplicationWindow类将实现DrawContents操作以绘制它所存储 View示例:
class ApplicationWindow : public Window
{
public:
    virtual void DrawContents();
};

void ApplicationWindow::DrawContents()
{
    GetView()->DrawOn(this);
}

又如,IconWindow存储了它所显示的图标对应的位图名。(代码省略) 我们还可以定义许多其他类型的窗口类。
Window的操作由WindowImp的接口定义。 例如,在调用WidowImp来操作在窗口中绘制矩形之前,DrawRect必须从它的两个Point参数中提取四个坐标值。
void Window::DrawRect(const Point& p1,const Point& p2)
{
    WindowImp* imp = GetWindowImp();
    imp->DeviceRect(p1.X(), p1.Y(), p2.X(), p2.Y());
}

具体的WindowImp子类可支持不同的窗口系统。XwindowImp子类支持XWindow窗口系统。
class XWindowImp : public WindowImp
{
public:
    XWindowImp();
       
    virtual void DeviceRect(Coord, Coord, Coord, Coord);
private:
    // lots of X Window system-specific state, including:
    Display* _dpy;
    Drawable _winid;
    GC _gc;
};

对于PM系统,我们定义PMWindowImp类。(代码省略)
这些子类用窗口系统的基本操作实现WindowImp的操作 如,X窗口系统这样实现DeviceRect:
void XWindowImp::DeviceRect()
{
    int x = round(min(x0, x1));
    int y = round(min(y0, y1));
    int w = round(abs(x0 - x1));
    int h = round(abs(x0 - x1));
    XDrawRectangle(_dpy, _winid, _gc, x, y, w, h);
}

而PM对相同操作的实现可能完全不一样,这使基于平台的实现。
那么一个窗口怎样得到正确而WindowImp子类的实例呢? 可以在Window的GetWindowImp操作中,从一个抽象工厂得到一个正确的实例。
WindowImp * Window::GetWindow() 
{
    if (_imp == 0)
    {
        _imp = WindowSystemFactory::Instance()->MakeWindowImp();    // WindowSystemFactory::Instance()函数返回一个抽象工厂
                                                                                                                      // 该工厂负责处理所有与特定窗口系统相关的对象
                                                                                                                      // 同时,这个抽象工厂实现称了一个单件(单例模式)
    }
    return _imp;
}

相关模式: 抽象工厂模式可以用来创建和配置一个特定的桥接模式。 适配器模式用来帮助无关的类协同工作。 桥接模式使得抽象接口和实现部分可以独立进行改变。

参考资料: 《设计模式:可复用面向对象软件的基础》