评论

收藏

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

网络安全 网络安全 发布于:2021-07-13 19:09 | 阅读数:605 | 评论:0

  说在前面的话:桥接模式(Bridge)会比较绕,所以我们打算换一种讲解方式,从一个例子从而引出桥接模式。
  设计模式学到最后,看起来既像这个,又像那个,不要在意这心,设计模式的核心是提升代码的扩展性,如果达到了这点,又何必在于是什么设计模式呢。
  一、场景问题
  1.1 故事场景
DSC0000.png

  经过多年爱情的经营,我和女朋友终于走到了婚姻的殿堂。
  结婚是一件开心的事情,但事情也特别多和杂…. 这不…. 我女朋友又找我来了…
  女朋友:亲爱的,你看下我整理了下名单。你给他们发送下信息。微信和手机短信就可以了。
  我:这么多人的吗?小几万人?咱们的关系网有这么大的吗?
  女朋友:你看我给分类了下:你的亲戚、我的亲戚;你的哥们、我的姐妹;你的朋友、我的朋友;你的…,我的…
  我:这工作量不小呢,我的好好研究一下。
  1.2 业务场景
  上面的这个场景,在我们的实际业务中就会碰到。比如:给要过期的企业(企业购买了年套餐),发送一条续费的消息,针对到期时间可能还会有不同的,比如:到期前30天发送微信消息,到期前15天发送短信消息,到期前7天发送加急消息或者直接电话通知等。
  二、消息发送1.0:只有消息发送方式
  2.1 设计
  根据我女朋友的要求就是能够使用微信和手机短信发送消息咯。
  由于发送消息会有两种不同的实现方式(微信和手机短信),为了让外部能统一操作,因此,把消息设计成接口,然后由两个不同的实现类,分别实现微信发送消息方式和手机短信发送消息的方式。
  根据我初步的设想,我想应该能满足我女朋友的要求,于是我就按照我的设想设计了一下(我们把当前发送消息的方式定义为普通消息):
DSC0001.png

  2.2 编码实现
  我们1个接口,两个实现类,这个还是很简单的,不多说:
  2.2.1 发送消息的接口
  发送消息的方式的接口Message:

  •  
package com.kfit.bridge.message.v1;/** * 发送消息的方式 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public interface Message {  /**   * 所有的消息类型都需要有发送消息的方法   * @param toUser : 消息要发送给谁   * @param message :发送消息的内容   */  void send(String toUser,String message);}
  2.2.2 发送消息的具体实现
  发送消息的方式的实现-微信发送消息CommonWeixinMessage:

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

  •  
package com.kfit.bridge.message.v1;/** * 发送消息的方式 - 手机短信 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public class CommonSMSMessage implements  Message {  @Override  public void send(String toUser, String message) {    //调用短信平台SDK进行发送消息    System.out.println("[手机短信消息] "+toUser+":"+message);  }}
  2.2.3 发送消息
  万事俱备,于是我就开始准备发送消息了:

  •  
package com.kfit.bridge.message.v1;/** * *  我来执行女朋友的的发送消息 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public class Me {  public static void main(String[] args) {    //初始化发送消息的方式    Message weixinMessage = new CommonWeixinMessage();    Message smsMessage = new CommonSMSMessage();    weixinMessage.send("鹏仔", "2021年x月x日,我要结婚了,记得来参加我的婚礼");    smsMessage.send("鹏仔", "2021年x月x日,我要结婚了,记得来参加我的婚礼");    weixinMessage.send("钟哥", "2021年x月x日,我要结婚了,记得来参加我的婚礼");    smsMessage.send("钟哥", "2021年x月x日,我要结婚了,记得来参加我的婚礼");    //... 其它人...  }}
  执行以下看下打印消息:
DSC0002.png

  三、消息发送2.0:加入消息类型
  消息发送之后,过了几天清闲的日子,刚躺着沙发上正要打开手机刷刷视频,女朋友的消息又来了。
  女朋友:你在忙吗?
  我:亲爱的,怎么了?有何事需要在下去办呐?
  女朋友:你看都快临近婚礼了,好多人也没有回复呢?你要不要加急一下。
  我:……
  3.1 需求分析
  我们这里先定义一下加急消息的概念:
  ②    加急消息会在消息上添加加急的标识;
  ② 加急会提供监控的方法,以便客户了解消息的处理进度。
  在上面的情节中就是:我发完消息之后,需要让对方给我一个回执,也就是给我发送一条确认消息之类的,然后我在汇报给女朋友大人。
  3.2 设计
  从一开始的需求到现在的需求,其实整个结构已经改变了。
  一开始就是一维的:发送消息的方式;现在已经转变为二维的:消息的类型。
  发送消息的方式:就是微信、手机短信。
  消息的类型:普通消息,加急消息。
  我们这里先不管这些,我们先看看我们常规的一个思路是怎么样子的:我们会抽象出来一个加急的接口UrgencyMessage,在此接口中会有一个watch方法,然后根据此接口还会有两个具体的实现微信发送方式、手机短信发送方式。
DSC0003.png

  3.3 编码
  我们新增1个接口,两个实现类:
  3.3.1 发送加急消息方式的接口
  加急消息UrgencyMessage继承接口Message,新增要给watch方法:

  •  
package com.kfit.bridge.message.v2;/** * * * 消息的类型 - 加急消息 * *  一开始的方式我们可以认为是普通消息。 *   * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public interface UrgencyMessage extends Message{  /**   * 监控某消息的处理过程   * @param messageId : 消息id   * @return   */   Object watch(String messageId);}
  3.3.2 发送加急消息方式的实现
  发送加急消息方式的实现UrgencyWeixinMessage:

  •  
package com.kfit.bridge.message.v2;/** * 发送加急消息的方式 - 手机短信 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public class UrgencyWeixinMessage implements UrgencyMessage {  @Override  public void send(String toUser, String message) {    message = "[加急]"+message;    //调用短信平台SDK进行发送消息    System.out.println("[微信消息] "+toUser+":"+message);  }  @Override  public Object watch(String messageId) {    //获取相应的数据,返回监控结果    return "收到,一定会去参加的";  }}
  发送加急消息方式的实现UrgencySMSMessage:

  •  
package com.kfit.bridge.message.v2;/** * 发送加急消息的方式 - 手机短信 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public class UrgencySMSMessage implements UrgencyMessage {  @Override  public void send(String toUser, String message) {    message = "[加急]"+message;    //调用短信平台SDK进行发送消息    System.out.println("[手机短信消息] "+toUser+":"+message);  }  @Override  public Object watch(String messageId) {    //获取相应的数据,返回监控结果    return "收到,一定会去参加的";  }}
  3.3.3 发送消息
  我们现在有监控的方法,就可以查看到消息的发送情况了:

  •  
/** * *  我来执行女朋友的的发送消息 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public class Me {  public static void main(String[] args) {    //初始化发送消息的方式    UrgencyMessage weixinMessage = new UrgencyWeixinMessage();    UrgencyMessage smsMessage = new UrgencySMSMessage();    weixinMessage.send("鹏仔", "2021年x月x日,我要结婚了,记得来参加我的婚礼");    System.out.println("获取反馈结果:"+weixinMessage.watch("1"));    smsMessage.send("鹏仔", "2021年x月x日,我要结婚了,记得来参加我的婚礼");    System.out.println("获取反馈结果:"+smsMessage.watch("2"));    weixinMessage.send("钟哥", "2021年x月x日,我要结婚了,记得来参加我的婚礼");    System.out.println("获取反馈结果:"+weixinMessage.watch("3"));    smsMessage.send("钟哥", "2021年x月x日,我要结婚了,记得来参加我的婚礼");    System.out.println("获取反馈结果:"+smsMessage.watch("4"));    //... 其它人...  }}
  查看下结果:
DSC0004.png

  四、消息发送3.0:二维扩展问题
  上面的设计感觉挺好的,没看出哪里有问题呀。系统问题的来源一般都是系统的升级产生的,我们接着衍化。
  加急消息发出去之后,好日子又过了一阵子。感觉女朋友总是能感觉我到过的太潇洒了似的。
  女朋友:你看你办的事情,怎么搞的,王某说过段时间在给答复,那现在到底是来还是来不来呢?
  我:这个我也不知道呢。
  女朋友:那现在都临近结婚日了,你赶紧催促催促问问呢。
  我:… (结个婚太难了…)
  女朋友:对了另外,有些朋友想要咱们的婚纱照,你用邮件给他们发一下。
  我:… (当场想跪下了…)
  4.1 加入特急消息的处理
  现在消息类型就从普通消息->加急消息->特急消息了,对于特急消息我们需要有一个催促的方法(urge)。
  这时候类图关系就变成这样子了:
DSC0005.png

  4.2 加入邮件发送消息的方式
  如果要添加一种新的发送消息的方式,比如邮件发送消息,是需要在每一种抽象的具体实现里面,都要添加邮件发送消息的处理。也就是说:发送普通消息、加急消息和特急消息的处理,都可以通过邮件来发送。这就意味着,需要添加三个实现。如下图所示:
DSC0006.png

  4.3 出现的问题
  通过继承来扩展的实现方式存在问题:
  扩展消息的类型(普通/加急/特急)不太容易,不同类型的消息具有不同的业务,也就是有不同的实现,在这种情况下,每个类型的消息,需要实现所有不同的消息方式(微信/邮件/手机短信)。
  如果要加入一种新的发送消息方式,那么会要求所有的消息类型,都要加入这种新的消息方式的实现。
我就是我,是颜色不一样的烟火。
我就是我,是与众不同的小苹果。
  à悟空学院: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

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