定义:
将抽象部分与它的实现部分分离,使它们都可以独立地变化
桥接模式原理的核心是抽象与抽象之间的分离,这样分离的好处就在于,具体的实现类依赖抽象而不是依赖具体,满足 DIP 原则,很好地完成了对象结构间的解耦。
换句话说,抽象的分离间接完成了具体类与具体类之间的解耦,它们之间使用抽象来进行组合或聚合,而不再使用继承
UML图
桥接模式主要包含了以下四个关键角色。
- 抽象实体:定义的一种抽象分类。比如,电脑中的 CPU、内存、摄像头、显示屏等
- 具体实体:继承抽象实体的子类实体。比如,Intel i7 CPU、三星内存、徕卡摄像头、京东方显示屏幕等
- 抽象行为:定义抽象实体中具备的多种行为。比如,CPU 逻辑运算、内存读写存储、摄像头拍照、屏幕显示图像等
- 具体行为:实现抽象行为的具体算法。比如,Intel 使用 X64 架构实现 CPU 逻辑运算,Mac M1 芯片使用 ARM 架构实现
CPU 逻辑运算,等等
/**
* @Description 抽象行为
*/
public abstract class AbstractBehavior {
public abstract void operation1();
public abstract void operation2();
}
public class DetailBehaviorA extends AbstractBehavior {
@Override
public void operation1() {
System.out.println("DetailBehaviorA operation1 ");
}
@Override
public void operation2() {
System.out.println("DetailBehaviorA operation2 ");
}
}
public class DetailBehaviorB extends AbstractBehavior {
@Override
public void operation1() {
System.out.println("DetailBehaviorB operation1 ");
}
@Override
public void operation2() {
System.out.println("DetailBehaviorB operation2 ");
}
}
/**
* @Description 抽象实体
*/
public abstract class AbstractEntity {
// 行为对象
protected AbstractBehavior abstractBehavior;
// 实体 与 行为 的关联
public AbstractEntity(AbstractBehavior abstractBehavior){
this.abstractBehavior = abstractBehavior;
}
// 子类需要实现的抽象方法
public abstract void request();
}
public class DetailEntityA extends AbstractEntity {
public DetailEntityA(AbstractBehavior abstractBehavior) {
super(abstractBehavior);
}
@Override
public void request() {
super.abstractBehavior.operation1();
}
}
public class DetailEntityB extends AbstractEntity {
public DetailEntityB(AbstractBehavior abstractBehavior) {
super(abstractBehavior);
}
@Override
public void request() {
super.abstractBehavior.operation2();
}
}
常用场景
- 需要提供平台独立性的应用程序时。 比如,不同数据库的 JDBC 驱动程序、硬盘驱动程序等
- 需要在某种统一协议下增加更多组件时。
比如,在支付场景中,我们期望支持微信、支付宝、各大银行的支付组件等。这里的统一协议是收款、支付、扣款,而组件就是微信、支付宝等 - 基于消息驱动的场景。
虽然消息的行为比较统一,主要包括发送、接收、处理和回执,但其实具体客户端的实现通常却各不相同,比如,手机短信、邮件消息、QQ 消息、微信消息等 - 拆分复杂的类对象时。 当一个类中包含大量对象和方法时,既不方便阅读,也不方便修改
- 希望从多个独立维度上扩展时。 比如,系统功能性和非功能性角度,业务或技术角度等
- 需要在运行时切换不同实现方法时。 比如,通过门面模式调用外部 RPC 服务
示例代码 1
public interface FileAbstractEntity {
Object update(String path);
boolean check(Object obj);
}
public class FileEntityImpl implements FileAbstractEntity {
private FileAbstractBehavior abstractBehavior;
public FileEntityImpl(FileAbstractBehavior abstractBehavior){
this.abstractBehavior = abstractBehavior;
}
@Override
public Object update(String path) {
return abstractBehavior.updateFile(path);
}
@Override
public boolean check(Object obj) {
return abstractBehavior.checkFile(obj);
}
}
public interface FileAbstractBehavior {
Object updateFile(String path);
boolean checkFile(Object obj);
}
public class LinuxFileBehavior implements FileAbstractBehavior {
@Override
public Object updateFile(String path) {
return null;
}
@Override
public boolean checkFile(Object obj) {
return false;
}
}
public class WindowsFileBehavior implements FileAbstractBehavior {
@Override
public Object updateFile(String path) {
return null;
}
@Override
public boolean checkFile(Object obj) {
return false;
}
}
对 FileAbstractBehavior 进行扩展
public interface ExtentFileAbstractBehavior extends FileAbstractBehavior {
/**
* 新操作删除
*
* @return
*/
boolean delete();
}
public class TencentFileBehavior implements ExtentFileAbstractBehavior {
@Override
public Object updateFile(String path) {
return null;
}
@Override
public boolean checkFile(Object obj) {
return false;
}
/**
* 新操作删除
*
* @return
*/
@Override
public boolean delete() {
return false;
}
}
/**
* @Description 新扩展的文件实体类, 实现了原来的 文件实体抽象方法
*/
public class OSSFileExtendEntity implements FileAbstractEntity {
private ExtentFileAbstractBehavior newFileBehavior;
public OSSFileExtendEntity(ExtentFileAbstractBehavior abstractBehavior){
this.newFileBehavior = abstractBehavior;
}
@Override
public Object update(String path) {
return newFileBehavior.updateFile(path);
}
@Override
public boolean check(Object obj) {
return newFileBehavior.checkFile(obj);
}
/**
* 新的文件实现
*
* @return
*/
public boolean del(){
return newFileBehavior.delete();
}
}
示例代码 2
public interface Brand {
void open();
void close();
void call();
}
public class Vivo implements Brand {
@Override
public void open() {
System.out.println("Vivo 开机");
}
@Override
public void close() {
System.out.println("Vivo 关机");
}
@Override
public void call() {
System.out.println("Vivo 打电话");
}
}
public class XiaoMi implements Brand {
@Override
public void open() {
System.out.println("Mi 开机");
}
@Override
public void close() {
System.out.println("Mi 关机");
}
@Override
public void call() {
System.out.println("Mi 打电话");
}
}
public abstract class Phone {
private Brand brand;
public Phone(Brand brand) {
this.brand = brand;
}
protected void open() {
this.brand.open();
}
protected void close() {
this.brand.close();
}
protected void call() {
this.brand.call();
}
}
public class FoldedPhone extends Phone {
public FoldedPhone(Brand brand) {
super(brand);
}
protected void open() {
super.open();
System.out.println("折叠手机");
}
protected void close() {
super.close();
System.out.println("折叠手机");
}
protected void call() {
super.call();
System.out.println("折叠手机");
}
}
public class UpRightPhone extends Phone {
public UpRightPhone(Brand brand) {
super(brand);
}
protected void open() {
super.open();
System.out.println("直立手机");
}
protected void close() {
super.close();
System.out.println("直立手机");
}
protected void call() {
super.call();
System.out.println("直立手机");
}
}
/**
* @Description 测试用例
*/
public class Client {
public static void main(String[] args) {
FoldedPhone foldedPhone = new FoldedPhone(new XiaoMi());
foldedPhone.open();
foldedPhone.call();
foldedPhone.close();
UpRightPhone upRightPhone = new UpRightPhone(new XiaoMi());
upRightPhone.open();
upRightPhone.call();
upRightPhone.close();
}
}