设计模式之桥接(Bridge)---对象结构性模式(设计模式笔记)
1.意图
将抽象部分与它的实现部分分离,使它们都可以独立地变化。
2.别名 Handle/Body
3.动机
当一个抽象可能有多个实现时,通常用继承来协调它们.但不够灵活.可以用Bridge模式.
4.适用性
1)你不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
2)类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时Bridge 模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
3)对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
4)(C + +)你想对客户完全隐藏抽象的实现部分。在C + +中,类的表示在类接口中是可见的。
5.结构
6.参与者
* Abstraction
---定义抽象类的接口.
---维护一个指向Implementor类型的指针.
*RefinedAbstraction
---扩充由Abstrastion定义的接口.
*Implementor
---定义实现类的接口,该接口不一定要与Abstraction接口完全一致;一般是: Implementor接口仅提供基本操作,而Abstraction则定义了基于这些基本操作的较高层次的操作.( 重点理解)
* ConcreteImplementor接口并定义它的具体实现.
7.协作:
Abstraction将Client的请求转发给它的Implementor对象.( 重点理解)
8.代码示例:
//------------------------------------------------------
/* 1)与模式对应关系
Abstraction----Window
RefineAbstraction---IconWindow&&ApplicationWindow
Implementor----ImpWindow
ConcreteImplementor---XWindowImp,PMWindowImp
2)结构图
*/
class Body {
public:
void Ref();
void Unref();
int RefCount();
private:
};
class Handle {
public:
Handle& operator=(const Handle& other);
private:
Body* _body;
};
/*
*/
Handle& Handle::operator= (const Handle& other) {
other._body->Ref();
_body->Unref();
if (_body->RefCount() == 0) {
delete _body;
}
_body = other._body;
return *this;
}
/*
*/
#include "Geom.H"
#include "math.h"
class Window;
class View {
public:
DrawOn(Window*);
};
class WindowImp;
struct Display;
typedef unsigned int Drawable;
typedef struct XXX { int y; } *GC;
extern XDrawRectangle(
Display*,
Drawable,
GC,
int,
int,
unsigned int,
unsigned int
);
struct PPOINTL {
Coord x;
Coord y;
};
const int GPI_ERROR = 1;
typedef int HPS;
int GpiBeginPath(HPS, unsigned long);
int GpiSetCurrentPosition(HPS, PPOINTL*);
int GpiPolyLine(HPS, unsigned long, PPOINTL*);
int GpiEndPath(HPS);
void ReportError();
void GpiStrokePath(HPS, unsigned long, unsigned long);
class WindowSystemFactory {
public:
static WindowSystemFactory* Instance();
WindowImp* MakeWindowImp();
};
/*
*/
class Window {
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 Point& at);
virtual void SetExtent(const Point& 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 Point&);
/*
*/
protected:
WindowImp* GetWindowImp();
View* GetView();
/*
*/
private:
WindowImp* _imp;
View* _contents; // the window's contents
};
/*
*/
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*, Coord, Coord) = 0;
// lots more functions for drawing on windows...
protected:
WindowImp();
};
/*
*/
class ApplicationWindow : public Window {
public:
// ...
virtual void DrawContents();
};
void ApplicationWindow::DrawContents () {
GetView()->DrawOn(this);
}
/*
*/
class IconWindow : public Window {
public:
// ...
virtual void DrawContents();
private:
const char* _bitmapName;
};
/*
*/
void IconWindow::DrawContents() {
WindowImp* imp = GetWindowImp();
if (imp != 0) {
imp->DeviceBitmap(_bitmapName, 0.0, 0.0);
}
}
/*
*/
void Window::DrawRect (const Point& p1, const Point& p2) {
WindowImp* imp = GetWindowImp();
imp->DeviceRect(p1.X(), p1.Y(), p2.X(), p2.Y());
}
/*
*/
class XWindowImp : public WindowImp {
public:
XWindowImp();
virtual void DeviceRect(Coord, Coord, 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
};
/*
*/
class PMWindowImp : public WindowImp {
public:
PMWindowImp();
virtual void DeviceRect(Coord, Coord, Coord, Coord);
// remainder of public interface...
private:
// lots of PM window system-specific state, including:
HPS _hps;
};
/*
*/
void XWindowImp::DeviceRect (
Coord x0, Coord y0, Coord x1, Coord y1
) {
int x = round(min(x0, x1));
int y = round(min(y0, y1));
int w = round(abs(x0 - x1));
int h = round(abs(y0 - y1));
XDrawRectangle(_dpy, _winid, _gc, x, y, w, h);
}
/*
*/
void PMWindowImp::DeviceRect (
Coord x0, Coord y0, Coord x1, Coord y1
) {
Coord left = min(x0, x1);
Coord right = max(x0, x1);
Coord bottom = min(y0, y1);
Coord top = max(y0, y1);
/*
*/
PPOINTL 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;
/*
*/
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);
}
}
/*
*/
WindowImp* Window::GetWindowImp () {
if (_imp == 0) {
_imp = WindowSystemFactory::Instance()->MakeWindowImp();
}
return _imp;
}
/*
*/
//---------------------------------------------------------------------------