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);
}那么一个窗口怎样得到正确而WindowImp子类的实例呢? 可以在Window的GetWindowImp操作中,从一个抽象工厂得到一个正确的实例。
WindowImp * Window::GetWindow()
{
if (_imp == 0)
{
_imp = WindowSystemFactory::Instance()->MakeWindowImp(); // WindowSystemFactory::Instance()函数返回一个抽象工厂
// 该工厂负责处理所有与特定窗口系统相关的对象
// 同时,这个抽象工厂实现称了一个单件(单例模式)
}
return _imp;
}相关模式: 抽象工厂模式可以用来创建和配置一个特定的桥接模式。 适配器模式用来帮助无关的类协同工作。 桥接模式使得抽象接口和实现部分可以独立进行改变。
参考资料: 《设计模式:可复用面向对象软件的基础》