将抽象部分与它的实现部分分离,使它们都可以独立地变化。
2. 别名
Handle / Body
3. 动机
当一个抽象可能有多个实现时,通常用继承来协调它们。抽象类定义对该抽象的接口,
而具体的子类则用不同方式加以实现。但是此方法有时不够灵活。继承机制将抽象部分与它
的实现部分固定在一起,使得难以对抽象部分和实现部分独立地进行修改、扩充和重用。
4.案例分析
假如我们有一个绘制窗口的基类Window,不同的平台绘制的方式不同。我们会为每一个平台写一个子类来继承Window,如下图
这里的XWindow和PMWindow 代表了两种不同的平台,这样做有什么问题呢?
(1)扩展 Wi ndow抽象使之适用于不同种类的窗口或新的系统平台很不方便。假设有Window的一个子类IconWindow,它专门将Window抽象用于图标处理。
为了使 IconWindow支持两个系统平台,我们必须实现两个新类 XIconWindow和PMIconWindow,更为糟糕的是,我们不得不为每一种类型的窗口都定义两个类。
而为了支持第三个系统平台我们还必须为每一种窗口定义一个新的Window子类,如下图所示。
(2)继承机制使得客户代码与平台相关。每当客户创建一个窗口时,必须要实例化一个具体的类,这个类有特定的实现部分。例如,创建 Xwindow对象会将Window抽象与XWindow的实现部分绑定起来,这使得客户程序依赖于 XWindow的实现部分。这将使得很难将客户代码移植到其他平台上去。
客户在创建窗口时应该不涉及到其具体实现部分。仅仅是窗口的实现部分依赖于应用运行的平台。这样客户代码在创建窗口时就不应涉及到特定的平台。
Bridge模式解决以上问题的方法是,将 Window抽象和它的实现部分分别放在独立的类层次结构中。其中一个类层次结构针对窗口接口(Window、IconWindow、TransientWindow) ,另外一个独立的类层次结构针对平台相关的窗口实现部分,这个类层次结构的根类为WindowImp。例如XwindowImp子类提供了一个基于XWindow系统的实现,如下页上图所示。对Window子类的所有操作都是用WindowImp接口中的抽象操作实现的。这就将窗口的抽象与系统平台相关的实现部分分离开来。因此,我们将 Window与WindowImp之间的关系称之为桥接,因为它在抽象类与它的实现之间起到了桥梁作用,使它们可以独立地变化。
5.结构
6. 参与者
• Abstraction (Window )
— 定义抽象类的接口。
— 维护一个指向Implementor类型对象的指针。
• RefinedAbstraction (IconWindow )
— 扩充由Abstraction定义的接口。
• Implementor (WindowImp )
— 定义实现类的接口,该接口不一定要与 Abstraction的接口完全一致;事实上这两个
接口可以完全不同。一般来讲, Implementor接口仅提供基本操作,而 Abstraction则
定义了基于这些基本操作的较高层次的操作。
• ConcreteImplementor (XwindowImp, PMWindowImp )
— 实现Implementor接口并定义它的具体实现。
7. 协作
• Abstraction将client的请求转发给它的Implementor对象。
8.代码实现
下面是创建的6个脚本,我们会一一分析
首先是window和IconWindow
window是绘制窗口的基类,IconWindow是绘制图表的,IconWindow继承自window。window及其子类中方法的实现由windowImp及其子类来实现
window代码
public class Window
{
public WindowImp GetWindowImp()
{
return WindowSystemFactory.GetInstance().GetWindowImp();
}
}
GetWindowImp方法运用WindowImp工厂的方法根据不同的平台返回不同的WindowImp的子类
public virtual void DrawIcon() {
WindowImp imp = GetWindowImp();
imp.DrawIcon();
}
接下来是WindowImp,XWindowImp,PMWindowImp
WindowImp是实现Window方法的基类,XWindowImp实现在X平台下的Window方法,PMWindowImp实现在PM平台下的方法
WindowImp代码
public class WindowImp {
public virtual void DrawIcon()
{
}
}
XWindowImp代码
public class XWindowImp : WindowImp
{
public override void DrawIcon()
{
}
}
PMWindowImp代码
public class PMWindowImp : WindowImp
{
public override void DrawIcon()
{
}
}
最后是WindowImp简单工厂WindowSystemFactory
public enum SystemWindow {
X,
PM
}
public class WindowSystemFactory {
public static SystemWindow systemWindow;
private static WindowSystemFactory instance;
public static WindowSystemFactory GetInstance() {
if (instance == null) {
instance = new WindowSystemFactory();
}
return instance;
}
public WindowImp GetWindowImp() {
WindowImp imp;
switch (systemWindow)
{
case SystemWindow.X:
imp = new XWindowImp();
break;
case SystemWindow.PM:
imp = new PMWindowImp();
break;
default:
imp = new WindowImp();
break;
}
return imp;
}
}