评论

收藏

[其他] 桥接模式之消息发送:结婚发消息不是一件简单的事情 - 第353篇

网络安全 网络安全 发布于:2021-07-13 20:12 | 阅读数:277 | 评论:0

  桥接模式基本概念
  用来解决上述问题的一个合理的解决方案,就是使用桥接模式(Bridge)。那么什么是桥接模式呢?
  一、桥接(Bridge)模式基本概念
  1.1 定义
  将抽象部分与它的实现部分分离,使它们都可以独立地变化。
  在上面的例子中我们之前分析了有两个维度:发送消息的方式和消息的类型。
  发送消息的方式:就是微信、手机短信、邮件。
  消息的类型:普通消息,加急消息、特急消息。
  那么这里的话,抽象部分实现部分是什么呢?消息发送的核心功能就是发送消息了,所以实现就是消息的发送方式(微信/手机短信/邮件)。那么抽象部分就是消息类型(普通/加急/特急)。
  1.2 应用桥接模式来解决的思路
  在上面的例子中我们之前分析了有两个维度:具体的消息发送的方式(微信/邮件/手机短信)和抽象的消息类型(普通/加急/加急)。
  这两个纬度一共可以组合出9种不同的可能性来(3x3=9)。
DSC0000.png

  我们在前面的编码问题就是:消息的抽象和实现是混杂在一起的,这就导致了,一个纬度的变化,会引起另一个纬度进行相应的变化,从而使得程序扩展起来非常困难。
  在桥接模式中解决的思路就是:把这两个纬度分开,也就是将抽象部分和实现部分分开,让它们相互独立,这样就可以实现独立的变化,使扩展变得简单。
  桥接模式通过引入实现的接口,把实现部分从系统中分离出去;那么,抽象这边如何使用具体的实现呢?肯定是面向实现的接口来编程了,为了让抽象这边能够很方便的与实现结合起来,把顶层的抽象接口改成抽象类,在里面持有一个具体的实现部分的实例。
  这样一来,对于需要发送消息的客户端而言,就只需要创建相应的消息对象,然后调用这个消息对象的方法就可以了,这个消息对象会调用持有的真正的消息发送方式来把消息发送出去。也就是说客户端只是想要发送消息而已,并不想关心具体如何发送。
  1.3 类图
DSC0001.png

  1.4 主要角色
  (1)抽象类(Abstraction):维护了Implementor即他的实现类,二者是聚合关系,Abstraction充当桥接类。
  (2)扩展抽象类(RefinedAbstraction):扩展抽象部分的接口,可以有多个。
  (3)实现接口(Implementor):定义实现部分的接口
  (4)具体实现(ConcreteImplementor):Implementor接口的具体实现,可以有多个。
  到这里我们对于桥接模式有了一个基本的了解,接下来我们用这个模式对于我们之前的代码进行优化。
  桥接模式之消息发送
  在上面我们对于桥接模式的定义有了一个基本的了解,接下来我们要重构我们之前的代码。
  一、消息发送4.0:桥接模式
  接下来我们根据桥接模式的定义来进行编码,主要分为两大部分抽象部分和实现部分。我们看下最终完成的类图:
DSC0002.png

  1.1 实现接口(Implementor)
  实现部分这里的例子中就是定义消息发送方式的一个接口即可,这里取名为MessageImplementor:

  •  
package com.kfit.bridge.message.v4;/** * * Implementor * * 定义实现类的接口,该接口不一定要与Abstraction的接口完全一致。事实上这两个接口可以完全不同。 * 一般来讲,Implementor接口仅提供基本操作,而Abstraction则定义了基于这些基本操作的较高层次的操作。 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public interface MessageImplementor {  /**   * 所有的消息类型都需要有发送消息的方法   * @param toUser : 消息要发送给谁   * @param message :发送消息的内容   */  void send(String toUser,String message);}
  1.2 具体实现(ConcreteImplementor)
  在这个例子中,我们主要有两种发送方式微信和手机短信,我们看下具体的实现:
  微信消息发送方式-WeixinMessage:

  •  
package com.kfit.bridge.message.v4;/** * 发送消息的方式 -  微信发送消息:际项目中应该是微信公众号的消息 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public class WeixinMessage implements  MessageImplementor {  @Override  public void send(String toUser, String message) {    //调用微信的SDK进行发送消息    System.out.println("[微信消息] "+toUser+":"+message);  }}
  手机短信发送方式-SMSMessage:

  •  
package com.kfit.bridge.message.v4;/** * 发送消息的方式 - 手机短信 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public class SMSMessage implements  MessageImplementor {  @Override  public void send(String toUser, String message) {    //调用短信平台SDK进行发送消息    System.out.println("[手机短信消息] "+toUser+":"+message);  }}
  1.3 抽象类(Abstraction)
  在例子中抽象部分就是消息的类型:普通消息、加急消息、特急消息。
  AbstractMessage:

  •  
package com.kfit.bridge.message.v4;/** * *定义抽象类的接口。维护一个指向Implementor类型对象的指针。 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public abstract class AbstractMessage {  /**   * 持有一个实现部分的对象   */  protected MessageImplementor impl;  public AbstractMessage(MessageImplementor impl) {    this.impl = impl;  }  /**   * 发送消息,转调实现部分的方法   * send 这个方法不要求和MessageImplementor的一样。   *   * @param toUser 消息发送的目的人员   * @param message 要发送的消息内容   */  public void send(String toUser,String message){    this.impl.send(toUser,message);  }}
  1.4 扩展抽象类(RefinedAbstraction)
  这里看下普通消息和加急消息的:
  普通消息方式-CommonMessage:

  •  
package com.kfit.bridge.message.v4;/** * * 普通消息的实现 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public class CommonMessage extends AbstractMessage{  public CommonMessage(MessageImplementor impl) {    super(impl);  }  @Override  public void send(String toUser, String message) {    //对于普通消息,什么都不干,直接调父类的方法,把消息发送出去就可以了    super.send(toUser, message);  }}
  加急消息方式-UrgencyMessage:

  •  
package com.kfit.bridge.message.v4;/** * * 加急消息的实现 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public class UrgencyMessage extends AbstractMessage{  public UrgencyMessage(MessageImplementor impl) {    super(impl);  }  @Override  public void send(String toUser, String message) {    message ="[加急]"+message;    super.send(toUser, message);  }  /**   * 扩展新功能:监控某消息的处理过程。   * @param messageId :消息编号   * @return   */  public Object watch(String messageId) {    //获取相应的数据,返回监控结果    return "[watch]收到,一定会去参加的";  }}
  1.5 小测
  到这里我们就可以进行测试一下了:

  •  
package com.kfit.bridge.message.v4;/** * * 发送消息测试 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public class Me {  public static void main(String[] args) {    //定义消息发送方式,如果要手机短信,直接换一个实现类即可:SMSMessage    MessageImplementor messageImplementor = new WeixinMessage();    /**     * 定义消息类型,可以和发送方式随意组合。     */    //创建一个普通消息对象    AbstractMessage message = new CommonMessage(messageImplementor);    message.send("鹏仔", "2021年x月x日,我要结婚了,记得来参加我的婚礼");    //加急消息    message = new UrgencyMessage(messageImplementor);    message.send("鹏仔", "2021年x月x日,我要结婚了,记得来参加我的婚礼");    //... 其它人...  }}
  打印结果:
DSC0003.png

  要想使用手机短信发送替换到具体的实现类即可。
  1.6 添加新的消息类型:加入特急消息
  那我们看看桥接模式是否可以解决我们上面碰到的问题:一个维度的变化会影响另外一个维度变化。
  我们现在要加入特急消息,只需要定义新的扩展抽象类即可,然后可以进行使用了。
  SpecialUrgencyMessage:

  •  
package com.kfit.bridge.message.v4;/** * 特急消息 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public class SpecialUrgencyMessage extends  AbstractMessage{  public SpecialUrgencyMessage(MessageImplementor impl) {    super(impl);  }  @Override  public void send(String toUser, String message) {    message = "[特急]"+message;    super.send(toUser, message);  }  /**   * 扩展新功能:催促   * @return   */  public void urge() {    System.out.println("[urge]->赶紧来...");  }}
  使用很简答:

  •  
//特急消息message = new SpecialUrgencyMessage(messageImplementor);message.send("鹏仔", "2021年x月x日,我要结婚了,记得来参加我的婚礼");
  1.6 添加新的消息发送方式:加入邮件发送方式
  我们要加入新的发送方式也很简单,只需要在新增一个具体实现即可。
  EmailMessage:

  •  
package com.kfit.bridge.message.v4;/** * 发送消息的方式 - 邮件发送方式 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public class EmailMessage implements  MessageImplementor {  @Override  public void send(String toUser, String message) {    //调用邮件服务    System.out.println("[邮件] "+toUser+":"+message);  }}
  1.7 小结
  采用桥接模式来实现过后,抽象部分和实现部分分离开了,可以相互独立的变化,而不会相互影响。因此在抽象部分添加新的消息类型,对发送消息的实现部分是没有影响的;反过来增加发送消息的方式,对消息类型也是没有影响的。
我就是我,是颜色不一样的烟火。
我就是我,是与众不同的小苹果。
  à悟空学院:https://t.cn/Rg3fKJD
  SpringBoot视频:http://t.cn/A6ZagYTi
  SpringBoot交流平台:https://t.cn/R3QDhU0
  SpringSecurity5.0视频:http://t.cn/A6ZadMBe
  ShardingJDBC分库分表:http://t.cn/A6ZarrqS
  分布式事务解决方案:http://t.cn/A6ZaBnIr
  JVM内存模型调优实战:http://t.cn/A6wWMVqG
  Spring入门到精通:https://t.cn/A6bFcDh4
  大话设计模式之爱你:https://dwz.cn/wqO0MAy7

  
关注下面的标签,发现更多相似文章