定义

将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化。

在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度?这就要使用Bridge模式。

我们来思考一下

如果我们需要做一个发送消息的系统,发送方式有站内消息和邮件两种,发送类型有普通和加急两种,我想大家都会很自然的想到下面的做法:

//消息接口
IMessage
//普通类型消息
CommonMessageSMS//站内发送
CommonMessageEmail//邮件发送
//加急类型消息
UrgentMessageSMS//站内发送
UrgentMessageEmail//邮件发送

好了,现在我们需要增加短信的发送方式和特级的发送类型,那么我们会发现这里出现了两个不同维度的变化,由于这两个维度相互关联,那么我们需要添加5个类才能完成需求,如下:

//为普通和加急类型的消息添加短信发送方式
CommonMessageMobile//短信发送
UrgentMessageMobile//短信发送
//添加特急类型的消息
SpecialUrgencyMessageSMS//站内发送
SpecialUrgencyMessageEmail//邮件发送
SpecialUrgencyMessageMobile//短信发送

现在我们发现,如果使用这种方式编写,当两个维度发生变化时,会导致类的数量暴增。如果使用桥接模式则可以缓解这个问题。

使用桥接模式时,我们将消息类型和发生方式脱耦,首先,我们将两个维度分开,我们需要一个消息类,该类只需要关注消息的类型即可,在抽象出一个消息发送类,该类只关注消息的发送方式;

消息类持有一个消息发送类的引用,通过改变传入的消息发送类达到动态的设定消息的发送方式。简单的说就是将继承改为聚合。

UML

优点

  1. 将实现予以解耦,让它和界面之间不再永久绑定;
  2. 抽象和实现可以独立扩展,不会影响到对方;
  3. 对于“具体的抽象类”所做的改变,不会影响到客户。

缺点

  1. 增加了复杂度;

应用场景

  1. 适合使用在需要跨越多个平台的图形和窗口上;
  2. 当需要用不同的方式改变接口和实现时,你会发现桥接模式很好用。

示例

我们使用桥接模式来实现一下上面的需求。

Java

 public class Main
{
public static void main(String[] args)
{
//创建具体的实现对象
MessageImplementor impl = new MessageSMS();
//创建一个普通消息对象
AbstractMessage m = new CommonMessage(impl);
m.sendMessage("请喝一杯茶", "小李");
//创建一个紧急消息对象
m = new UrgencyMessage(impl);
m.sendMessage("请喝一杯茶", "小李");
//创建一个特急消息对象
m = new SpecialUrgencyMessage(impl);
m.sendMessage("请喝一杯茶", "小李"); //把实现方式切换成手机短消息,然后再实现一遍
impl = new MessageMobile();
m = new CommonMessage(impl);
m.sendMessage("请喝一杯茶", "小李");
m = new UrgencyMessage(impl);
m.sendMessage("请喝一杯茶", "小李");
m = new SpecialUrgencyMessage(impl);
m.sendMessage("请喝一杯茶", "小李");
} /**
* 消息发送方式的接口
*/
public static interface MessageImplementor
{
void send(String message,String toUser);
} /**
* 消息抽象类
*/
public static abstract class AbstractMessage
{
protected MessageImplementor impl; public AbstractMessage(MessageImplementor impl)
{
this.impl = impl;
} public void sendMessage(String message,String toUser)
{
this.impl.send(message, toUser);
}
} /**
* 站内发送消息实现类
*/
public static class MessageSMS implements MessageImplementor
{
public void send(String message, String toUser)
{
System.out.println("使用站内短消息的方式,发送消息'" + message + "'给" + toUser);
}
} /**
* 电子邮件发送消息实现类
*/
public static class MessageEmail implements MessageImplementor
{
public void send(String message, String toUser)
{
System.out.println("使用Email的方式,发送消息'" + message + "'给" + toUser);
}
} /**
* 普通消息类
*/
public static class CommonMessage extends AbstractMessage
{
public CommonMessage(MessageImplementor impl)
{
super(impl);
} public void sendMessage(String message, String toUser)
{
//对于普通消息,什么都不干,直接调父类的方法,把消息发送出去就可以了
super.sendMessage(message, toUser);
}
} /**
* 加急消息类
*/
public static class UrgencyMessage extends AbstractMessage
{
public UrgencyMessage(MessageImplementor impl)
{
super(impl);
} public void sendMessage(String message, String toUser)
{
message = "加急:" + message;
super.sendMessage(message, toUser);
} public Object watch(String messageId)
{
//获取相应的数据,组织成监控的数据对象,然后返回
return null;
}
} /**
* 短信发送消息实现类
*/
public static class MessageMobile implements MessageImplementor
{
public void send(String message, String toUser)
{
System.out.println("使用手机短消息的方式,发送消息'"+message+"'给"+toUser);
}
} /**
* 特急消息类
*/
public static class SpecialUrgencyMessage extends AbstractMessage
{
public SpecialUrgencyMessage(MessageImplementor impl)
{
super(impl);
} public void hurry(String messageId)
{
//执行催促的业务,发出催促的信息
} public void sendMessage(String message, String toUser)
{
message = "特急:"+message;
super.sendMessage(message, toUser);
//还需要增加一条待催促的信息
}
}
}

最新文章

  1. 双击导航栏自动滑动ListView到顶部
  2. 规则引擎集成接口(九)Java类对象
  3. 第 20 章 CSS3 前缀和 rem
  4. python中利用logging包进行日志记录时的logging.level设置选择
  5. swift学习笔记之-错误处理
  6. 利用select函数的定时返回功能在Windows上实现微秒级的cpu休眠
  7. linuxserver启动过程
  8. Swift 常用字符串操作
  9. SQL语句查询某字段不同数据的个数(DISTINCT 的使用)
  10. StackExchange.Redis学习笔记(四) 事务控制和Batch批量操作
  11. final关键字细节
  12. 学习日志1 :java 三大框架 了解
  13. H5页面长按导致app崩溃问题解决
  14. Yahoo Programming Contest 2019 E - Odd Subrectangles
  15. 纯C:AES256
  16. iOS设置tableViewCell之间的间距(去掉UItableview headerview黏性)
  17. Unity3D学习笔记(五):坐标系、向量、3D数学
  18. PHP CI框架如何去掉 sql 里的反引号
  19. Center Alignment
  20. vtk 基础概念

热门文章

  1. Java 动态写轮眼 SharinganJPanel (整理)
  2. 一起学CUDA(一)
  3. Linux/Unix shell 脚本监控磁盘可用空间
  4. Android 高仿UC浏览器监控剪切板弹出悬浮窗功能
  5. MongoDB配置客户端
  6. background-size background-positon合并的写法
  7. sessionFactory.getCurrentSession()的引出
  8. top命令 Linux查看CPU和内存使用情况
  9. nmon基础
  10. python字典概述