先看一个栗子
有个需求,需要创建不同的图形,每个图形都有不同的颜色。用传统的继承方式是这么实现的:首先创建一个图形接口,接口中有个画图的方法。然后创建接口的实现类,比如圆形、长方形、正方形。每个图形下面又有子类,比如白色圆形、黑色圆形、白色长方形、黑色长方形等等。
但是,上面的实现方式有个很大的弊端就是不利于扩展,当需要红色图形时,所有的图形都要增加红色的子类,当再多增加几种颜色时…类将会变得越来越庞大,形成类爆炸。还不止如此,如果需要增加一种图形的话,比如三角形,还需要增加三角形的各种颜色的子类…慢慢的也会形成类爆炸。
为了解决上述问题,桥接模式应运而生。
定义
将抽象与实现分离,使它们可以独立变化。他是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
结构
桥接(Bridge)模式包含以下主要角色:
抽象化角色:定义抽象类,并包含一个对实现化对象的引用。
扩展抽象化角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
实现化角色:定义实现化角色的接口,供扩展抽象化角色调用。
具体实现化角色:给出实现化角色接口的具体实现。
看上面的定义比较抽象,看不懂没关系,看完下面的案例就明白了。
案例
需要开发一个跨平台视频播放器,可以在不同操作系统(如Windows、Mac、Linux等)上播放多种格式(如RMVB、AVI、WMV等)的视频文件。该播放器包含了两个维度操作系统和视频格式,适合使用桥接模式。
上图的结构关系:OperatingSystem(抽象化角色)、Windows和Mac(扩展抽象化角色)、VideoFile(实现化角色)、AVIFile和RMVBFile(具体实现化角色)。
VideoFile
package com.hupp.bridge;
public interface VideoFile {
void decode(String fileName);
}
AVIFile
package com.hupp.bridge;
public class AVIFile implements VideoFile{
@Override
public void decode(String fileName) {
System.out.println("播放avi视频文件:"+fileName);
}
}
RMVBFile
package com.hupp.bridge;
public class RMVBFile implements VideoFile{
@Override
public void decode(String fileName) {
System.out.println("播放rmvb视频文件:"+fileName);
}
}
OperatingSystem
package com.hupp.bridge;
public abstract class OperatingSystem {
//声明VideoFile对象
protected VideoFile videoFile;
public OperatingSystem(VideoFile videoFile){
this.videoFile=videoFile;
}
//抽象方法,播放功能
public abstract void play(String fileName);
}
Windows
package com.hupp.bridge;
public class Windows extends OperatingSystem{
public Windows(VideoFile videoFile) {
super(videoFile);
}
@Override
public void play(String fileName) {
videoFile.decode(fileName);
}
}
Mac
package com.hupp.bridge;
public class Mac extends OperatingSystem{
public Mac(VideoFile videoFile) {
super(videoFile);
}
@Override
public void play(String fileName) {
videoFile.decode(fileName);
}
}
客户端
package com.hupp.bridge;
public class Client {
public static void main(String[] args) {
OperatingSystem system = new Mac(new AVIFile());
system.play("小黄人.大眼萌.avi");
}
}
执行结果
总结:桥接模式提高了系统的可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统,遵守了开闭原则。