桥接模式
桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
在有多种可能会变化的情况下,用继承会造成类很多,扩展起来不灵活,因此使用桥接模式将抽象部分与实现部分分离,使它们都可以独立的变化。 桥接模式优点:
- 1、抽象和实现的分离。
- 2、优秀的扩展能力。
- 3、实现细节对客户透明。
下面结合案例进行简单的介绍。
案例分析
本次采用的是比较经典的大家都熟悉的案例,是某年软件设计师的试题。具体如下:
现欲实现一个图像浏览系统,要求该系统能够显示BMP、JPEG和GIF三种格式的文件,并且能够在 Windows和 Linux两种操作系统上运行。系统首先将BMP、JPEG和GIF三种格式的文件解析为像素矩阵,然后将像素矩阵显示在屏幕上。系统需具有较好的扩展性以支持新的文件格式和操作系统。为满足上述需求并减少所需生成的子类数目,采用桥接( Bridge设计模式进行设计,所得类图如下图所示。
通过题干分析可以知道需要读取的文件格式可能是多种的,而且可能在不同的操作系统中去展示图像,而需要将文件的展示与系统的实现集合起来。经过分析,文件的格式可能是多种多样的,操作系统也是多种多样的,因此使用桥接模式对该题设计比较好。 下面开始进行简单代码实现。下图是建好的文件。
编写图像展示抽象类
编写图像展示抽象类,是为了在后期,新加入不同的操作系统之后,只需要集成此抽象类,就可以快速实现不同类型文件的图像展示。使图像文件类型与操作系统之间进行解耦。 编写代码如下,只有一个图像输出的方法。
/** * @ClassName ImageHandler * @Description: * @Author 公众号:Java全栈架构师 * @Version V1.0 **/ public abstract class ImageHandler { public abstract void doPaint(PictureElement pe); }
其中PictureElement 是展示的图像像素点,由于是模拟展示,本次针对此对象只显示文件名称。
/** * @ClassName PictureElement * @Description: * @Author 公众号:Java全栈架构师 * @Version V1.0 **/ public class PictureElement { private String fileName; public String getFileName() { return fileName; } public PictureElement(String fileName) { this.fileName = fileName; } public void setFileName(String fileName) { this.fileName = fileName; } }
Linux系统展示
/** * @ClassName LinuxImageImpl * @Description: * @Author 公众号:Java全栈架构师 * @Version V1.0 **/ public class LinuxImageImpl extends ImageHandler { @Override public void doPaint(PictureElement pe) { System.out.println("Linux 输出图像。文件名称是:" + pe.getFileName()); } }
Windows系统展示
/** * @ClassName WinImageImpl * @Description: * @Author 公众号:Java全栈架构师 * @Version V1.0 **/ public class WinImageImpl extends ImageHandler { @Override public void doPaint(PictureElement pe) { System.out.println("Windows 输出图像。文件名称是:" + pe.getFileName()); } }
编写图像文件处理类
创建一个抽象ImageInfo的类,其中包含图像显示类和图像文件转换类两个。
/** * @ClassName ImageInfo * @Description: * @Author 公众号:Java全栈架构师 * @Version V1.0 **/ public abstract class ImageInfo { protected ImageHandler imageHandler; public void setImageHandler(ImageHandler image) { this.imageHandler = image; } public abstract void parseFile(String fileName); }
编写不同文件处理方法
JPEG文件处理。
/** * @ClassName JPEG * @Description: * @Author 公众号:Java全栈架构师 * @Version V1.0 **/ public class JPEG extends ImageInfo { @Override public void parseFile(String fileName) { System.out.println("将JPEG格式文件转成图像像素矩阵对象"); PictureElement pe = new PictureElement(fileName); imageHandler.doPaint(pe); } }
GIF文件处理。
/** * @ClassName GIF * @Description: * @Author 公众号:Java全栈架构师 * @Version V1.0 **/ public class GIF extends ImageInfo { @Override public void parseFile(String fileName) { System.out.println("将GIF格式文件转成图像像素矩阵对象"); PictureElement pe = new PictureElement(fileName); imageHandler.doPaint(pe); } }
BMP文件处理。
/** * @ClassName BMP * @Description: * @Author 公众号:Java全栈架构师 * @Version V1.0 **/ public class BMP extends ImageInfo { @Override public void parseFile(String fileName) { System.out.println("将BMP格式文件转成图像像素矩阵对象"); PictureElement pe = new PictureElement(fileName); imageHandler.doPaint(pe); } }
运行
通过main运行一下简单的测试类可以看到运行结果如下。
/** * @ClassName MainApplication * @Description: * @Author 公众号:Java全栈架构师 * @Version V1.0 **/ public class MainApplication { public static void main(String[] args) { //在 Linux 查看GIF图片 ImageInfo imageInfoGIF = new GIF(); LinuxImageImpl linuxImage = new LinuxImageImpl(); imageInfoGIF.setImageHandler(linuxImage); imageInfoGIF.parseFile("test.GIF"); //在 Windows 查看JPEG图片 ImageInfo imageInfoJPEG = new JPEG(); WinImageImpl winImage = new WinImageImpl(); imageInfoJPEG.setImageHandler(winImage); imageInfoJPEG.parseFile("test.JPEG"); } }
运行结果:
将GIF格式文件转成图像像素矩阵对象 Linux 输出图像。文件名称是:test.GIF 将JPEG格式文件转成图像像素矩阵对象 Windows 输出图像。文件名称是:test.JPEG 复制代码
好了,一个简单的桥接模式就介绍完成了,学习设计模式的时候,尽量结合熟悉的案例进行分析,这样的话就会有事半功倍的奇效,也更容易理解。大家可以尝试着在项目中使用设计模式的方式进行开发。