Skip to content

桥接模式实现不同维度短信发送

概述

桥接模式的主要作用是通过将抽象部分与实现部分分离,使得它们可以独立地扩展,而不会相互影响,把多种可匹配的进行组合,也就是 A 类中含有 B 类接口,通过构造函数传递 B 类的实现, 一般含有多种维度就可以采用桥接模式,比如存在嵌套 if 的语法就可以考虑采用

适用场景

  1. 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系
  2. 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用
  3. 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展

相关角色

  • Abstraction

抽象化角色: 主要职责定义该角色的行为,同时保存一个对实现化角色的引用,该角色一般是抽象类

  • Implementor

实现化角色:抽象或者抽象类,定义角色必需的行为和属性

  • RefinedAbstraction

扩展抽象化角色:它引用实现化角色对抽象化角色进行修正

  • ConcreteImplementor

具体实现化角色:它实现接口或抽象类定义的方法和属性。

案例

在发送短信的时候我们有不同的通道,比如短信发送,邮件发送, 同时我们消息由不同的消息类型, 加急消息,普通短信, 同时我们需要这些短信类型可以支持采用不同的通道来发送

定义 Implementor 角色 MessageSend

java
public interface MessageSend {

    void send(String message, String target);
}

实现 ConcreteImplementor 角色 EmailMessageSend,SmsMessageSend

java
@Component
@Slf4j
public class EmailMessageSend implements MessageSend {
    @Override
    public void send(String message, String target) {
        log.info("Use email send message :{} to user :{}",message,target);
    }

}


@Component
@Slf4j
public class SmsMessageSend implements MessageSend {
    @Override
    public void send(String message, String target) {
        log.info("use SMS send message :{} to :{}",message,target);
    }
}

定义 Abstraction 抽象化角色

java
public abstract class AbstractMessageSend {

    // 持有实现部分的对象
    private final MessageSend messageSend;

    // 构造器传入实现部分的对象
    public AbstractMessageSend(MessageSend messageSend) {
        this.messageSend = messageSend;
    }

    // 发送消息,委派实现部分的方法
    public void sendMessage(String message,String target) {
        this.messageSend.send(message,target);
    }
}

具体 RefinedAbstraction 角色 NormalMessageSend,

java
public class NormalMessageSend extends AbstractMessageSend {

    public NormalMessageSend(MessageSend messageSend) {
        super(messageSend);
    }

    @Override
    public void sendMessage(String message, String target) {
        //对于普通消息,直接调用父类方法发送消息即可
        super.sendMessage(message, target);
    }
}

public class UrgencyMessageSend extends AbstractMessageSend {

    public UrgencyMessageSend(MessageSend messageSend) {
        super(messageSend);
    }

    @Override
    public void sendMessage(String message, String target) {
        message = "加急:" + message;
        // 扩展相关功能
        super.sendMessage(message, target);
    }
}

配置类

一般 SpringBoot 的服务类都是无状态的,我们创建一个配置类,将这些服务注入到 spring 容器中

java
@Component
public class MessageBridgeConfig {

    private final MessageSend emailMessageSend;

    private final MessageSend smsMessageSend;

    public MessageBridgeConfig(MessageSend emailMessageSend, MessageSend smsMessageSend) {
        this.emailMessageSend = emailMessageSend;
        this.smsMessageSend = smsMessageSend;
    }

    @Bean
    public NormalMessageSend normalMessageSendWithEmail() {
        return new NormalMessageSend(emailMessageSend);
    }

    @Bean
    public NormalMessageSend normalMessageSendWithSms() {
        return new NormalMessageSend(smsMessageSend);
    }


    @Bean
    public UrgencyMessageSend urgencyMessageSendWithEmail() {
        return new UrgencyMessageSend(emailMessageSend);
    }

    @Bean
    public UrgencyMessageSend urgencyMessageSendWithSms() {
        return new UrgencyMessageSend(smsMessageSend);
    }
}

测试用例

java

@SpringBootTest(classes = DesignPatternsApplication.class)
public class DesignPatternsApplicationTest {

    // 注入邮件发送普通消息
    @Autowired
    NormalMessageSend normalMessageSendWithEmail;

    // 注入短信发送普通消息
    @Autowired
    NormalMessageSend normalMessageSendWithSms;

    // 注入邮件发送加急消息
    @Autowired
    UrgencyMessageSend urgencyMessageSendWithEmail;

    // 注入短信发送加急消息
    @Autowired
    UrgencyMessageSend urgencyMessageSendWithSms;

    @Test
    public void test() {
        String targetEmail = "chengdong2518@163.com";
        String targetPhone = "1591xxxxxxx";
        normalMessageSendWithEmail.sendMessage("邮件发送普通消息",targetEmail);
        normalMessageSendWithSms.sendMessage("短信发送普通消息",targetPhone);

        urgencyMessageSendWithEmail.sendMessage("邮件发送加急消息",targetEmail);
        urgencyMessageSendWithSms.sendMessage("短信发送加急消息",targetPhone);
    }
}

结果输出

text
2024-08-15 11:19:53.734  INFO 23072 --- [           main] c.s.d.p.s.bridge.send.EmailMessageSend   : Use email send message :邮件发送普通消息 to user :chengdong2518@163.com
2024-08-15 11:19:53.734  INFO 23072 --- [           main] c.s.d.p.s.bridge.send.SmsMessageSend     : use SMS send message :短信发送普通消息 to :1591xxxxxxx
2024-08-15 11:19:53.735  INFO 23072 --- [           main] c.s.d.p.s.bridge.send.EmailMessageSend   : Use email send message :加急:邮件发送加急消息 to user :chengdong2518@163.com
2024-08-15 11:19:53.735  INFO 23072 --- [           main] c.s.d.p.s.bridge.send.SmsMessageSend     : use SMS send message :加急:短信发送加急消息 to :1591xxxxxxx

UML 关系图

bridge

总结

定义新的消息通道实现 MessageSend 以及扩展 AbstractMessageSend 我们就可以很容易的将系统进行扩展

Released under the MIT License.