设计模式-桥接模式
定义
桥接模式又叫桥梁模式、接口模式或柄体模式。是将抽象的部分和实现的部分分离开来,使它们可以独立变化
通过组合的方式建立两个类之间的联系,而不是继承。
属于结构型模式。
适用场景
- 在抽象和具体实现之间需要增加更多的灵活性的场景。
- 一个类存在两个独立变化的维度,而这两个维度都需要独立进行扩展。
- 不希望使用继承,或者多层继承导致系统类的个数剧增。
例子
代码示例:
UML 类图:
新建一个IMessage消息接口类,有一个sendMessage 方法:
/**
* 消息接口类
* @author black
*
*/
public interface IMessage {
/**
* 发送消息
* @param message 消息题
* @param recvUser 接收者
*/
void sendMessage(String message, String recvUser);
}
根据【消息发送方式】维度,新建邮件消息类:
package com.black.design.pattern.bridge.general;
/**
* 邮件消息
* @author black
*
*/
public class EmailMessage implements IMessage {
public void sendMessage(String message, String recvUser) {
System.out.println("发送邮件【"+message+"】给" + recvUser);
}
}
根据【消息发送方式】维度,新建短信消息类:
package com.black.design.pattern.bridge.general;
/**
* 短信消息
* @author black
*
*/
public class SmsMessage implements IMessage {
public void sendMessage(String message, String recvUser) {
System.out.println("发送短信【"+message+"】给" + recvUser);
}
}
根据【消息类型】维度,新建普通消息类:
package com.black.design.pattern.bridge.general;
/**
* 普通消息
* @author black
*
*/
public class NormalMessage implements IMessage {
public void sendMessage(String message, String recvUser) {
message = "【普通】" + message;
System.out.println("发送"+message+"给" + recvUser);
}
}
根据【消息类型】维度,新建紧急消息类:
package com.black.design.pattern.bridge.general;
/**
* 紧急消息
* @author black
*
*/
public class EmergencyMessage implements IMessage {
public void sendMessage(String message, String recvUser) {
message = "【紧急】" + message;
System.out.println("发送"+message+"给" + recvUser);
}
}
这时候,我想在邮件消息或者短信发送时,将消息的紧急程度加上,于是进行以下改造:
- 根据【发送消息方式】抽象出一个抽象类
- 抽象类构造方法注入 【消息类型】的IMessage接口类
改造后的UML 类图:
其中,AbstractMessage就是一个桥,通过组合方式,引入了同一接口另一个维度。
改造后代码:
IMessage 接口类不变:
package com.black.design.pattern.bridge.general;
/**
* 消息接口类
* @author black
*
*/
public interface IMessage {
/**
* 发送消息
* @param message 消息题
* @param recvUser 接收者
*/
void sendMessage(String message, String recvUser);
}
【发送消息方式】维度抽象出一个 AbstractMessage 抽象类,构造方法注入【消息类型】维度 :
package com.black.design.pattern.bridge.general;
/**
* 作为桥梁引入【消息类型】
* @author black
*
*/
public class AbstractMessage implements IMessage {
//引入另一变化维度
private IMessage msgType;
public AbstractMessage(IMessage messageType) {
this.msgType = messageType;
}
//调用【消息类型】纬度的sendMessage方法
public void sendMessage(String message, String recvUser) {
msgType.sendMessage(message, recvUser);
}
}
EmailMessage 类继承 AbstractMessage 类,委托父类进行发送消息:
package com.black.design.pattern.bridge.general;
/**
* 发送消息方式-邮件
* @author black
*
*/
public class EmailMessage extends AbstractMessage{
public EmailMessage(IMessage messageType) {
super(messageType);
}
public void sendMessage(String message, String recvUser) {
// 添加消息发送方式
message = "邮件【" + message +"】";
super.sendMessage(message, recvUser);
}
}
SmsMessage 类继承 AbstractMessage 类,委托父类进行发送消息:
package com.black.design.pattern.bridge.general;
/**
* 发送消息方式-短信
* @author black
*
*/
public class SmsMessage extends AbstractMessage{
public SmsMessage(IMessage messageType) {
super(messageType);
}
public void sendMessage(String message, String recvUser) {
// 添加消息发送方式
message = "短信【" + message +"】";
super.sendMessage(message, recvUser);
}
}
NormalMessage 类不变:
package com.black.design.pattern.bridge.general;
/**
* 普通消息
* @author black
*
*/
public class NormalMessage implements IMessage {
public void sendMessage(String message, String recvUser) {
message = "【普通】" + message;
System.out.println("发送"+message+"给" + recvUser);
}
}
EmergencyMessage 类不变:
package com.black.design.pattern.bridge.general;
/**
* 紧急消息
* @author black
*
*/
public class EmergencyMessage implements IMessage {
public void sendMessage(String message, String recvUser) {
message = "【紧急】" + message;
System.out.println("发送"+message+"给" + recvUser);
}
}
测试类:
package com.black.design.pattern.bridge.general;
public class MessageTest {
public static void main(String[] args) {
//发送普通短信给black
IMessage normalMsg = new NormalMessage();
IMessage sms = new SmsMessage(normalMsg);
sms.sendMessage("吃饭了吗?","black");
//发送紧急邮件给black
IMessage emergencyMsg = new EmergencyMessage();
IMessage email = new EmailMessage(emergencyMsg);
email.sendMessage("赶紧回来吃饭!","black");
}
}
测试结果:
发送【普通】短信【吃饭了吗?】给black
发送【紧急】邮件【赶紧回来吃饭!】给black
最后,可能发现,这个例子和【装饰器】模式很像,但是仔细看看会发现,【装饰器】模式是通过继承,而【桥接】模式是通过组合模式。
优点
- 分离抽象部分和具体实现部分
- 提高系统扩展性
- 符合开闭原则
- 符合合成复用原则
缺点
- 增加系统理解与设计难度
- 需要正确识别系统中两个独立变化的维度