桥接模式之消息发送

桥接模式之消息发送

桥接模式基本概念

用来解决上述问题的一个合理的解决方案,就是使用桥接模式(Bridge)。那么什么是桥接模式呢?

一、桥接(Bridge)模式基本概念

1.1 定义

将抽象部分与它的实现部分分离,使它们都可以独立地变化。

在上面的例子中我们之前分析了有两个维度:发送消息的方式和消息的类型。

发送消息的方式:就是微信、手机短信、邮件。

消息的类型:普通消息,加急消息、特急消息。

那么这里的话,抽象部分实现部分是什么呢?消息发送的核心功能就是发送消息了,所以实现就是消息的发送方式(微信/手机短信/邮件)。那么抽象部分就是消息类型(普通/加急/特急)。

1.2 应用桥接模式来解决的思路

在上面的例子中我们之前分析了有两个维度:具体的消息发送的方式(微信/邮件/手机短信)和抽象的消息类型(普通/加急/加急)。

这两个纬度一共可以组合出9种不同的可能性来(3×3=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 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日,我要结婚了,记得来参加我的婚礼");

        //... 其它人...
    }
}

复制代码

打印结果:

图片

要想使用手机短信发送替换到具体的实现类即可。

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 小结

采用桥接模式来实现过后,抽象部分和实现部分分离开了,可以相互独立的变化,而不会相互影响。因此在抽象部分添加新的消息类型,对发送消息的实现部分是没有影响的;反过来增加发送消息的方式,对消息类型也是没有影响的。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享