一、什么是桥接模式
桥接模式是一种结构型设计模式。它将抽象部分和实现部分分离,使它们可以独立地变化。
二、角色组成
抽象部分(Abstraction):定义了抽象部分的接口,并包含对实现部分的引用。
实现部分(Implementor):定义了实现部分的接口。
具体抽象(Concrete Abstraction):继承抽象部分,实现其中定义的抽象方法。
具体实现(Concrete Implementor):实现Implementor,实现其中定义的具体行为。
三、优缺点
优点:
分离抽象和实现,使得它们可以独立变化。
提高了系统的灵活性和可扩展性。
隐藏了具体的实现细节,使系统更加稳定和可靠。
符合开闭原则,可以方便地增加新的抽象和实现部分。
缺点:
需要定义抽象部分和实现部分之间的桥接接口,增加了系统的复杂性。
如果一个类有多个变化的维度,使用桥接模式可能会导致类的数量增多,增加了系统的复杂性和维护成本。
四、应用场景
4.1 生活场景
墙上的开关:可以看到的开关是抽象的,不用管里面具体怎么实现的。
蓝牙耳机与手机:蓝牙耳机可以连接不同品牌的手机,那么手机就可以看作是抽象部分,蓝牙耳机是实现部分,实现不同蓝牙耳机与不同手机的连接和通讯。
遥控器和电视:同样道理,遥控器可以控制不同品牌的电视,遥控器可以作为抽象部分,电视则作为实现部分,实现不同遥控器与不同电视的连接和操作。
4.2 java场景
JdbcTemplate:用于简化数据库操作的类,它使用了桥接模式将数据库的访问方式(如JDBC、Hibernate、MyBatis)与具体的实现(Oracle、Mysql、SQL
Server)分离,这样可以方便地切换不同的数据库访问方式。
Spring的DI和IOC:抽象部分定义了接口或抽象类。比如BeanFactory,而实现部分则由具体的实现类(XmlBeanFactory等)提供。
日志框架:抽象部分定义了一组日志记录接口,并提供了不通过的日志记录方法,如DEBUG、INFO、ERROR等,实现部分则通过具体的日志实现类提供实际的日志记录功能,如Log4j、Logback等。
五、代码实现
下面是一个蓝牙耳机和手机的简单例子,用来解释桥接模式。手机作为抽象部分,蓝牙耳机作为实现部分。通过抽象类对实现类接口的引用,使手机可以调用蓝牙接口的方法,实现手机与蓝牙耳机的连接和调用的解耦。
抽象部分:Phone
实现部分:Bluetooth
具体抽象:HWPhone、IPhone
具体实现:BluetoothImpl
5.0 UML类图
5.1 实现部分——Bluetooth
/**
*
* 1.实现部分(Implementor):蓝牙接口
*/
public interface Bluetooth {
//连接
void connect();
//断开
void disConnect();
}
5.2 具体实现——BluetoothImpl
/**
*
* 2.具体实现(Concrete Implementor):实现蓝牙接口
*/
public class BluetoothImpl implements Bluetooth{
@Override
public void connect() {
System.out.println("蓝牙已连接!");
}
@Override
public void disConnect() {
System.out.println("蓝牙已断开!");
}
}
5.3 抽象部分——Phone
/**
*
* 3.抽象部分(Abstraction):手机抽象类
*/
public abstract class Phone {
//蓝牙接口实例
protected Bluetooth bluetooth;
public Phone(Bluetooth bluetooth){
this.bluetooth=bluetooth;
}
//手机具体功能,调用蓝牙接口的方法
public abstract void bluetoothFunction();
}
5.4 具体抽象
/**
*
* 4.具体抽象:苹果手机
*/
public class IPhone extends Phone{
public IPhone(Bluetooth bluetooth) {
super(bluetooth);
}
//手机具体功能,调用蓝牙
@Override
public void bluetoothFunction() {
System.out.println("苹果手机使用蓝牙耳机");
bluetooth.connect();
bluetooth.disConnect();
}
}
/**
*
* 4.具体抽象:华为手机
*/
public class HWPhone extends Phone{
public HWPhone(Bluetooth bluetooth) {
super(bluetooth);
}
//手机具体功能,调用蓝牙
@Override
public void bluetoothFunction() {
System.out.println("华为手机使用蓝牙耳机");
bluetooth.connect();
bluetooth.disConnect();
}
}
5.5 TestBridge
/**
*
* 桥接模式测试类
*/
@SpringBootTest
public class TestBridge {
@Test
void testBridge(){
//1 创建蓝牙耳机对象
Bluetooth bluetooth=new BluetoothImpl();
//2.创建不同品牌的手机对象
//苹果
Phone iPhone=new IPhone(bluetooth);
//华为
Phone hw=new HWPhone(bluetooth);
//调用手机的具体功能方法
iPhone.bluetoothFunction();
System.out.println("=========================");
hw.bluetoothFunction();
}
}
六、总结
当一个类需要两个或多个变化维度时:桥接模式可以将这些变化维度分离出来,使它们可以独立变化。例如,在一个图形编辑器中,图形和颜色可以被视为两个变化的维度,通过使用桥接模式,可以实现不同图形和不同颜色的组合。
当需要实现多层继承时:使用继承会导致类层次结构的爆炸性增长,难以维护和扩展。而桥接模式通过将抽象部分和实现部分分离,使得新增功能可以通过组合来实现,而不是通过继承。
当需要在抽象部分和实现部分之间增加灵活性时:桥接模式允许抽象部分和实现部分可以独立变化,提供了更大的灵活性和可配置性。例如,在一个电商平台中,抽象部分可以是商品,实现部分可以是支付方式,通过桥接模式可以在运行时选择不同的支付方式。
当需要对抽象和实现部分进行扩展时:桥接模式允许抽象部分和实现部分可以独立扩展,而不会相互影响。例如,在一个电子设备管理系统中,抽象部分可以是设备接口,实现部分可以是不同类型的设备,通过桥接模式可以方便地添加新的设备类型。
总结:桥接模式适用于多维度变化、多层继承、灵活性要求高、扩展性高的场景。