文章目录
- 桥接模式
- 1.桥接模式的本质
- 2.何时选用桥接模式
- 3.优缺点
- 4.桥接模式的结构
- 5.实现
- 模拟消息发送
- MVC在桥接模式的体现
桥接模式
桥接模式实质就是分离抽象和实现,抽象部分有多种,实现部分有多种,耦合在一起很难扩展,将其分离开来就很容易扩展,结构也清晰了
1.桥接模式的本质
桥接模式的本质:分离抽象和实现。
桥接模式最重要的工作就是分离抽象部分和实现部分,这是解决问题的关键。只有把抽象部分和实现部分分离开了,才能够让它们独立地变化;只有抽象部分和实现部分可以独立地变化,系统才会有更好的可扩展性和可维护性。
2.何时选用桥接模式
建议在以下情况中选用桥接模式。
-
如果你不希望在抽象部分和实现部分采用固定的绑定关系,可以采用桥接模式,来把抽象部分和实现部分分开,然后在程序运行期间来动态地设置抽象部分需要用到的具体的实现,还可以动态地切换具体的实现。
-
如果出现抽象部分和实现部分都能够扩展的情况,可以采用桥接模式,让抽象部分和实现部分独立地变化,从而灵活地进行单独扩展,而不是搅在一起,扩展一边就会影响到另一边。
-
如果希望实现部分的修改不会对客户产生影响,可以采用桥接模式。由于客户是面向抽象的接口在运行,实现部分的修改可以独立于抽象部分,并不会对客户产生影响,也可以说对客户是透明的。
-
如果采用继承的实现方案,会导致产生很多子类,对于这种情况,可以考虑采用桥接模式,分析功能变化的原因,看看是否能分离成不同的纬度,然后通过桥接模式来分离它们,从而减少子类的数目。
3.优缺点
桥接模式的优点
-
分离抽象和实现部分
桥接模式分离了抽象部分和实现部分,从而极大地提高了系统的灵活性。让抽象部分和实现部分独立开来,分别定义接口,这有助于对系统进行分层,从而产生更好的结构化的系统。对于系统的高层部分,只需要知道抽象部分和实现部分的接口就可以了。 -
更好的扩展性
由于桥接模式把抽象部分和实现部分分离开了,而且分别定义接口,这就使得抽象部分和实现部分可以分别独立地扩展,而不会相互影响,从而大大地提高了系统的可扩展性。 -
可动态地切换实现
由于桥接模式把抽象部分和实现部分分离开了,所以在实现桥接的时候,就可以实现动态的选择和使用具体的实现。也就是说一个实现不再是固定的绑定在一个抽象接口上了,可以实现运行期间动态地切换。 -
可减少子类的个数
根据前面的讲述,对于有两个变化纬度的情况,如果采用继承的实现方式,大约需要两个纬度上的可变化数量的乘积个子类;而采用桥接模式来实现,大约需要两个纬度上的可变化数量的和个子类。可以明显地减少子类的个数。
4.桥接模式的结构
-
Abstraction:抽象部分的接口。通常在这个对象中,要维护一个实现部分的对象引用,抽象对象里面的方法,需要调用实现部分的对象来完成。这个对象中的方法,通常都是和具体的业务相关的方法。
-
RefinedAbstraction:扩展抽象部分的接口。通常在这些对象中,定义跟实际业务相关的方法,这些方法的实现通常会使用Abstraction中定义的方法,也可能需要调用实现部分的对象来完成。
-
Implementor:定义实现部分的接口。这个接口不用和 Abstraction中的方法一致,通常是由Implementor 接口提供基本的操作。而Abstraction中定义的是基于这些基本操作的业务方法,也就是说Abstraction定义了基于这些基本操作的较高层次的操作。
-
ConcreteImplementor:真正实现Implementor接口的对象。
5.实现
模拟消息发送
模拟发送消息,发送方式可以是短信发送、邮件发送,消息类型可以是普通消息、加急消息
有以下组合:
- 短信-普通消息
- 短信-加急消息
- 邮件-普通消息
- 邮件-加急消息
1.发送消息方式接口及其实现类
/**
* @description:发送消息方式接口
*/
public interface Message {
/**
* 发送消息
* @param message 消息内容
* @param toUser 给谁发的消息
*/
void send(String message,String toUser);
}
/**
* @description:短信消息
*/
public class SMSMessage implements Message {
@Override
public void send(String message, String toUser) {
System.out.println("发送短信消息,内容:" + message + ",发送给:" + toUser);
}
}
/**
* @description:邮件消息
*/
public class EmailMessage implements Message {
@Override
public void send(String message, String toUser) {
System.out.println("发送邮件消息,内容:" + message + ",发送给:" + toUser);
}
}
2.消息类型抽象类及其实现
/**
* @description:消息类型
*/
@AllArgsConstructor
public abstract class AbstractMessage {
protected Message messageImplementor;
public void sendMessage(String message, String toUser) {
messageImplementor.send(message,toUser);
}
}
/**
* @description:普通消息
*/
public class CommonMessage extends AbstractMessage {
public CommonMessage(Message messageImplementor) {
super(messageImplementor);
}
@Override
public void sendMessage(String message, String toUser) {
super.sendMessage(message, toUser);
}
}
/**
* @description:加急消息
*/
public class UrgentMessage extends AbstractMessage {
public UrgentMessage(Message messageImplementor) {
super(messageImplementor);
}
@Override
public void sendMessage(String message, String toUser) {
message = "加急:" + message;
super.sendMessage(message, toUser);
}
}
3.测试类
public class Client {
public static void main(String[] args) {
//短信消息
Message sms=new SMSMessage();
//邮件消息
Message email=new EmailMessage();
//短信普通消息
new CommonMessage(sms).sendMessage("普通消息","张三");
//邮件普通消息
new CommonMessage(email).sendMessage("普通消息","张三");
//短信加急消息
new UrgentMessage(sms).sendMessage("加急消息","李四");
//邮件加急消息
new UrgentMessage(email).sendMessage("加急消息","李四");
}
}
4.结果
如果想增加消息发送方式
或消息类型
,只需要增加一个类实现对应接口或抽象类即可。
MVC在桥接模式的体现
其实MVC模式就是一种桥接模式,如下图
这样看不太明显,如果service有多个实现再看呢,Controller中的两个方法相当于两个实现类,可以调用serviceImpl1也可以调用serviceImpl2