桥接模式之消息发送:结婚发消息不是一件简单的事情 - 第353篇
桥接模式基本概念用来解决上述问题的一个合理的解决方案,就是使用桥接模式(Bridge)。那么什么是桥接模式呢?
一、桥接(Bridge)模式基本概念
1.1 定义
将抽象部分与它的实现部分分离,使它们都可以独立地变化。
在上面的例子中我们之前分析了有两个维度:发送消息的方式和消息的类型。
发送消息的方式:就是微信、手机短信、邮件。
消息的类型:普通消息,加急消息、特急消息。
那么这里的话,抽象部分实现部分是什么呢?消息发送的核心功能就是发送消息了,所以实现就是消息的发送方式(微信/手机短信/邮件)。那么抽象部分就是消息类型(普通/加急/特急)。
1.2 应用桥接模式来解决的思路
在上面的例子中我们之前分析了有两个维度:具体的消息发送的方式(微信/邮件/手机短信)和抽象的消息类型(普通/加急/加急)。
这两个纬度一共可以组合出9种不同的可能性来(3x3=9)。
我们在前面的编码问题就是:消息的抽象和实现是混杂在一起的,这就导致了,一个纬度的变化,会引起另一个纬度进行相应的变化,从而使得程序扩展起来非常困难。
在桥接模式中解决的思路就是:把这两个纬度分开,也就是将抽象部分和实现部分分开,让它们相互独立,这样就可以实现独立的变化,使扩展变得简单。
桥接模式通过引入实现的接口,把实现部分从系统中分离出去;那么,抽象这边如何使用具体的实现呢?肯定是面向实现的接口来编程了,为了让抽象这边能够很方便的与实现结合起来,把顶层的抽象接口改成抽象类,在里面持有一个具体的实现部分的实例。
这样一来,对于需要发送消息的客户端而言,就只需要创建相应的消息对象,然后调用这个消息对象的方法就可以了,这个消息对象会调用持有的真正的消息发送方式来把消息发送出去。也就是说客户端只是想要发送消息而已,并不想关心具体如何发送。
1.3 类图
1.4 主要角色
(1)抽象类(Abstraction):维护了Implementor即他的实现类,二者是聚合关系,Abstraction充当桥接类。
(2)扩展抽象类(RefinedAbstraction):扩展抽象部分的接口,可以有多个。
(3)实现接口(Implementor):定义实现部分的接口
(4)具体实现(ConcreteImplementor):Implementor接口的具体实现,可以有多个。
到这里我们对于桥接模式有了一个基本的了解,接下来我们用这个模式对于我们之前的代码进行优化。
桥接模式之消息发送
在上面我们对于桥接模式的定义有了一个基本的了解,接下来我们要重构我们之前的代码。
一、消息发送4.0:桥接模式
接下来我们根据桥接模式的定义来进行编码,主要分为两大部分抽象部分和实现部分。我们看下最终完成的类图:
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 implementsMessageImplementor { @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 implementsMessageImplementor { @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 "收到,一定会去参加的"; }} 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日,我要结婚了,记得来参加我的婚礼"); //... 其它人... }} 打印结果:
要想使用手机短信发送替换到具体的实现类即可。
1.6 添加新的消息类型:加入特急消息
那我们看看桥接模式是否可以解决我们上面碰到的问题:一个维度的变化会影响另外一个维度变化。
我们现在要加入特急消息,只需要定义新的扩展抽象类即可,然后可以进行使用了。
SpecialUrgencyMessage:
[*]
package com.kfit.bridge.message.v4;/** * 特急消息 * * @author 悟纤「公众号SpringBoot」 * @date 2020-11-27 * @slogan 大道至简 悟在天成 */public class SpecialUrgencyMessage extendsAbstractMessage{ 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("->赶紧来..."); }} 使用很简答:
[*]
//特急消息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 implementsMessageImplementor { @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
文档来源:51CTO技术博客https://blog.51cto.com/u_11142439/3064829
页:
[1]