设计模式学习 - 桥接模式

何为桥接模式?举个例子,假如需要大、中、小三种型号的蜡笔,且每种型号的笔都能绘制12种不同的颜色,那就需要36支笔。如果是毛笔,那就只需要3种型号的笔,和12种颜色的调色板。如果新增一种型号的笔,蜡笔还需要新增12支,而毛笔只需一支,因为有调色板。在蜡笔中,颜色和型号两个不同的变化维度耦合在一起,不管对哪一个进行扩展,都会影响另外一个维度。而毛笔不同,不管是扩展型号还是颜色,不会影响另外一个。蜡笔存在较强的耦合性,毛笔将二者解耦,使用起来灵活,扩展也方便。

定义

将抽象部分与它的实现部分解耦,使得二者都可以独立变化。

结构

Abstraction(抽象类)

它是用于定义抽象类的接口,通常是抽象类而不是接口,其中定义了Implementor(实现类接口)类型的对象并维护它,它与Implementor之间具有关联关系,它既可以包含抽象业务方法,也可以包含具体业务方法。

RefinedAbstraction(扩充抽象类)

它扩充由Abstraction定义的接口,通常情况下,它不再是抽象类,而是具体类,实现了在Abstraction中声明的抽象业务方法,在RefinedAbstraction中可以调用在Implementor中定义的业务方法。

Implementor(实现类接口)

它是定义实现类的接口,这个接口不一定要与Abstraction的接口完全一致,事实上这两个接口可以完全不同。一般而言,Implementor接口仅提供基本操作,而Abstraction定义的接口可能会做更多更复杂的操作。Implementor接口对这些基本操作进行了声明,而具体实现交给了其子类。通过关联关系,在Abstraction中不仅拥有自己的方法,还可以调用到Implementor中定义的方法,使用关联关系来代替继承关系。

ConcreteImplemtor(具体实现类)

它具体实现了Implementor接口,在不同的ConcreteImplemtor中提供基本操作的不同实现,在程序运行时ConcreteImplementor对象将替换其父类对象,提供给抽象类具体的业务操作方法。

举例说明

通过一个不同系统,显示不同格式图片的例子来进行说明这个设计模式。不同操作系统,显示图片的方法不同。

1.需要一个辅助类,该类不用实现,这里只是模拟这样一个过程

// 辅助类 - 各种格式的图像文件最终转换成像素矩阵
public class Matrix {
	// xxx
}

2.实现接口类和具体实现类 

/**
 *  实现接口类(Implementor) - 操作系统接口
 *  提供显示图像的方法
 */
public interface Os {
	/**
	 * 显示像素矩阵m
	 * @param m
	 */
	public void doPaint(Matrix m);
}
/**
 * 具体实现类 - Windows系统
 * 实现Windows中显示图像的方法
 */
public class WindowsImp implements Os{

	@Override
	public void doPaint(Matrix m) {
		System.out.println("在Windows中显示图像:");
	}

}
/**
 * 具体实现类 - Linux系统
 * 实现Linux中显示图像的方法
 */
public class LinuxImp implements Os{

	@Override
	public void doPaint(Matrix m) {
		System.out.println("在Linux中显示图像:");
	}

}

3.抽象类和扩充抽象类

// 抽象类(Abstraction) - 抽象图像类
public abstract class Image {
	// 操作系统
	protected Os os;
	
	public void setOs(Os os) {
		this.os = os;
	}
	
	/**
	 * 解析文件
	 * @param fileName 文件名
	 */
	public abstract void parseFile(String fileName);
	
}
// 扩充抽象类 - PNG格式图像类
public class PNGImage extends Image{

	@Override
	public void parseFile(String fileName) {
		// 模拟解析PNG文件
		Matrix m = new Matrix();
		os.doPaint(m);
		System.out.println(fileName + ",格式为PNG.");
	}

}
//扩充抽象类 - JPG格式图像类
public class JPGImage extends Image{

	@Override
	public void parseFile(String fileName) {
		// 模拟解析PNG文件
		Matrix m = new Matrix();
		os.doPaint(m);
		System.out.println(fileName + ",格式为JPG.");
	}

}

4.测试类

public class Client {
	public static void main(String[] args) {
		// Windows操作系统
		Os os = new WindowsImp();
		// PNG格式
		Image img = new PNGImage();
		img.setOs(os);
		img.parseFile("Vae");
		System.out.println("--------------");
		// Linux操作系统
		os = new LinuxImp();
		// JPG格式
		img = new JPGImage();
		img.setOs(os);
		img.parseFile("Jay");
	}
}

5.结果截图

优点

1.分离抽象接口及其实现部分。解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。也就是说抽象和实现不在同一个继承层次结构中,而是“子类化”他们,使它们各自具有自己的子类,以便以任意组合。

2.很多情况下,它取代多层继承方案,极大减少了子类个数。

3.提高了系统的可扩展性

缺点

1.会增加系统的理解与设计难度,关联关系建立在抽象层

2.使用范围具有一定局限性,如何正确识别两个维度需要一定的经验积累。

在软件开发中,适配器模式通常和桥接模式联合使用。

发布了59 篇原创文章 · 获赞 13 · 访问量 2527

猜你喜欢

转载自blog.csdn.net/qq_40885085/article/details/103383007
今日推荐