设计模式(七)桥接

一、定义

将抽象部分与它的实现部分解耦,使两者都能够独立变化,桥接模式是一种结构型模式。

二、描述

包含以下四个角色:

1、Abstraction(抽象类):它是用于定义抽象类的接口,通常是抽象类而不是接口,其中定义了一个Implementor(实现类接口)类型的对象并可以维护该对象,它与Implementor之间具有关联关系,既可以包含抽象业务方法,也可以包含具体业务方法。
2、RefinedAbstratction(扩充抽象类):它扩充由Abstraction定义的接口,通常情况下他不再是抽象类而是具体类,实现了在Abstraction中声明的抽象业务方法,在RefinedAbstraction中可以调用在Implementor中定义的业务方法。
3、Implementor(实现类接口):它是定义实现类的接口,这个接口不一定要与Abstraction的接口完全一致,事实上两个接口可以完全不同。一般而言,Implementor只提供基本操作,而Abstraction定义的接口可能会做更多更复杂的操作。Implementor接口对这些基本操作进行了声明,而将具体实现交给其子类。通过关联关系,在Abstraction中不仅可以拥有自己的方法,还可以调用Implementor中定义的方法,使用关联关系来替代继承关系。
4、ConcreteImplementor(具体实现类):它具体实现Implementor接口,在不同的ConcreteImplementor中提供基本操作的不同实现,在程序运行时,ConcreteImplentor对象将替换其父类对象,提供给抽象类具体的业务操作方法。

三、例子

X公司想要开发一个跨平台的图像浏览系统,要求该系统能够显示JPG、BMP、GIF、PNG等多种格式的文件,并且能够在Windows、Linux以及Unix等多个操作系统上运行。该系统首先将各种格式的文件解析为像素矩阵(Matrix),然后将像素矩阵显示在屏幕上,在不同的操作系统中可以调用不同的绘制函数来绘制像素矩阵。该系统需要具备较好的扩展性以支持新的文件格式和操作系统。

Matrix:像素矩阵类,辅助类,各种格式的图像文件最终都会被转化为像素矩阵,不同的操作系统提供不同的方式显示像素矩阵

public class Matrix
{
    // 省略实现代码
}

Image:抽象图像类,充当抽象类

public abstract class Image
{
    protected ImageImplementor imageImpl;

    public void SetImageImplementor (ImageImplementor imageImpl)
    {
        this.imageImpl = imageImpl;
    }

    public abstract void ParstFile(string fileName);
}

JPGImage、BMPImage、GIFImage:扩充抽象类

public class JPGImage : Image
{
    public override void ParstFile(string fileName)
    {
        // 模拟解析JPG文件并获得一个像素矩阵对象m
        Matrix m = new Matrix();
        imageImpl.DoPaint(m);
        Console.WriteLine("{0} : 格式为JPG", fileName);
    }
}

public class BMPImage : Image
{
    public override void ParstFile(string fileName)
    {
        // 模拟解析BMP文件并获得一个像素矩阵对象m
        Matrix m = new Matrix();
        imageImpl.DoPaint(m);
        Console.WriteLine("{0} : 格式为BMP", fileName);
    }
}

public class GIFImage : Image
{
    public override void ParstFile(string fileName)
    {
        // 模拟解析GIF文件并获得一个像素矩阵对象m
        Matrix m = new Matrix();
        imageImpl.DoPaint(m);
        Console.WriteLine("{0} : 格式为GIF", fileName);
    }
}

ImageImplementor:抽象操作系统实现类

public interface ImageImplementor
{
    // 显示像素矩阵
    void DoPaint(Matrix m);
}

WindowsImplementor、LinuxImplementor、UnixImplementor:具体实现类

public class WindowsImplementor : ImageImplementor
{
    public void DoPaint(Matrix m)
    {
        // 调用Windows的绘制函数绘制像素矩阵
        Console.WriteLine("在Windows系统中显示图像");
    }
}

public class LinuxImplementor : ImageImplementor
{
    public void DoPaint(Matrix m)
    {
        // 调用Linux的绘制函数绘制像素矩阵
        Console.WriteLine("在Linux系统中显示图像");
    }
}

public class UnixImplementor : ImageImplementor
{
    public void DoPaint(Matrix m)
    {
        // 调用Unix的绘制函数绘制像素矩阵
        Console.WriteLine("在Unix系统中显示图像");
    }
}

Program:测试代码

Matrix m = new Matrix();
ImageImplementor wi = new WindowsImplementor();
Image ji = new JPGImage();
ji.SetImageImplementor(wi);
ji.ParstFile("小龙女");
Console.ReadLine();

四、总结

1、优点

(1)分离抽象接口及其实现部分,桥接模式使用“对象间的关联关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度变化。
(2)取代多层继承方案,极大地减少了子类的个数。
(3)提高了系统可扩展性,在两个变化维度中任意扩展一个维度,不需要修改原有系统,符合开闭原则。

2、缺点

(1)增加了系统的理解和设计难度,需要开发者在一开始就对抽象层进行设计与编程。
(2)要求正确识别出系统中两个独立变化的维度,如何正确地识别需要一定的经验积累。

热门相关:藏娇记事   一等狂妃:邪王,请接招!   魔神狂后   女大学生练歌厅   有了继父的女儿