桥接模式的定义
桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(interface)模式。
桥接模式的概念较为抽象,需结合例子才能更好理解。话不多说,直接看下面的例子~
模拟获得不同品牌不同类型的电脑例子
假设我们的程序需求是要获得不同品牌不同类型的电脑(比如有台式机和笔记本类型、有联想和苹果品牌)。
按照一般的思路,我们首先定义一个电脑类,然后定义不同类型的电脑(如台式机、笔记本)继承电脑类;而每个类型的电脑又有不同的品牌。于是乎,又接着定义不同品牌的电脑继承自对应类型的电脑(即一种多重继承的结构)。
如果此时需要进行拓展,比如新增一个品牌,那么我们就要在每个类型的电脑下都定义一个新的子类,如 xxx 牌电脑,这样做十分冗余且麻烦。
解决办法就是对它们进行一个拆解,将抽象与实现部分分离,让它们都可以独立地变化,即对电脑与品牌进行了解耦,由此引入桥接模式对其进行改进。
使用桥接模式进行设计的思路结构图如下所示:
形象一点说就是:通过中间的一座桥梁(将抽象品牌接口组合在电脑中),使得两个维度(电脑 + 品牌)能够通过组合的方式,得到我们的目标(不同品牌 + 不同类型的电脑),这样做极大的减少了子类的个数并且提高了系统的可扩展性(好处)。
(1)首先,定义抽象的品牌接口:
/**
* 品牌接口
*/
public interface Brand {
void name();
}
(2)定义不同品牌,即品牌接口的具体实现类:
public class Lenovo implements Brand {
@Override
public void name() {
System.out.print("联想");
}
}
public class Apple implements Brand {
@Override
public void name() {
System.out.print("苹果");
}
}
(3)定义电脑类,其中组合了抽象的品牌接口:
/**
* 电脑抽象类,其中通过组合 Brand 接口实现桥接
*/
public abstract class Computer {
protected Brand brand;
public Computer(Brand brand) {
this.brand = brand;
}
public void showBrand() {
brand.name();
}
}
(4)定义不同类型的电脑,继承自抽象电脑类:
/**
* 台式机,继承自抽象电脑类
*/
public class Desktop extends Computer {
public Desktop(Brand brand) {
super(brand);
}
@Override
public void showBrand() {
super.showBrand();
System.out.print("台式机\n");
}
}
/**
* 笔记本,继承自抽象电脑类
*/
public class Laptop extends Computer {
public Laptop(Brand brand) {
super(brand);
}
@Override
public void showBrand() {
super.showBrand();
System.out.print("笔记本\n");
}
}
(5)定义客户端:通过组合的方式得到不同品牌不同类型的电脑:
/**
* 客户端只需要传入电脑类型 + 品牌即可组合成不同品牌的不同类型的电脑
*/
public class Client {
public static void main(String[] args) {
Computer computer1 = new Desktop(new Lenovo());
Computer computer2 = new Laptop(new Apple());
computer1.showBrand();
computer2.showBrand();
}
}
(6)运行结果
联想台式机
苹果笔记本
优点:
(1)提高系统可拓展性:使用桥接模式后,当我们想要扩展电脑或者品牌的时候,只需要对它们各自进行扩展即可。
(2)极大的减少子类的个数,是对多继承的一种很好解决方案。
缺点:
(1)增加系统的理解与设计难度:需要我们有一定的抽象能力。
(2)具有一定局限性,针对的是独立变化的维度。