《用户通知体系全流程实战》
第4章 通知渠道适配器模式
4、通知渠道适配器模式:适配器设计模式、各渠道(邮件、短信、推送)适配器实现
在用户通知体系中,不同的通知渠道(邮件、短信、App推送)拥有各自独立的API和协议。为了统一调用方式、降低系统耦合度,我们引入适配器设计模式。适配器模式如同一个“万能插头转换器”,将不同渠道的差异接口转换为统一的INotificationChannel接口,让上层业务代码无需关心底层实现细节。
📐 适配器设计模式核心概念
🎯 适配器模式三要素
- 🔹 目标接口(Target) — 统一的通知发送接口
- 🔹 适配者(Adaptee) — 各渠道原生SDK/API
- 🔹 适配器(Adapter) — 将Adaptee转换为Target
⚙️ 适配器模式优势
- ✅ 开闭原则 — 新增渠道无需修改现有代码
- ✅ 单一职责 — 每个适配器只处理一种渠道
- ✅ 统一调用 — 业务层只需面向接口编程
📧 邮件渠道适配器实现
📌 适配目标:将 JavaMail / SendGrid 等邮件SDK统一为 INotificationChannel
// 目标接口
public interface INotificationChannel {
boolean send(NotificationRequest request);
ChannelType getType();
}
// 邮件适配器
public class EmailAdapter implements INotificationChannel {
private final JavaMailSender mailSender; // 适配者
public EmailAdapter(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
@Override
public boolean send(NotificationRequest request) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo(request.getRecipient());
helper.setSubject(request.getTitle());
helper.setText(request.getContent(), true); // 支持HTML
mailSender.send(message);
return true;
} catch (Exception e) {
log.error("邮件发送失败: {}", e.getMessage());
return false;
}
}
@Override
public ChannelType getType() {
return ChannelType.EMAIL;
}
}
📱 短信渠道适配器实现
📌 适配目标:将阿里云短信 / Twilio 等短信SDK统一为 INotificationChannel
// 短信适配器
public class SmsAdapter implements INotificationChannel {
private final AliyunSmsClient smsClient; // 适配者
public SmsAdapter(AliyunSmsClient smsClient) {
this.smsClient = smsClient;
}
@Override
public boolean send(NotificationRequest request) {
try {
SendSmsRequest smsReq = new SendSmsRequest()
.setPhoneNumbers(request.getRecipient())
.setSignName("通知系统")
.setTemplateCode("SMS_123456")
.setTemplateParam("{\"code\":\"" + request.getContent() + "\"}");
SendSmsResponse response = smsClient.sendSms(smsReq);
return "OK".equals(response.getCode());
} catch (Exception e) {
log.error("短信发送失败: {}", e.getMessage());
return false;
}
}
@Override
public ChannelType getType() {
return ChannelType.SMS;
}
}
🔔 App推送渠道适配器实现
📌 适配目标:将极光推送 / Firebase Cloud Messaging 统一为 INotificationChannel
// 推送适配器
public class PushAdapter implements INotificationChannel {
private final JPushClient jpushClient; // 适配者
public PushAdapter(JPushClient jpushClient) {
this.jpushClient = jpushClient;
}
@Override
public boolean send(NotificationRequest request) {
try {
PushPayload payload = PushPayload.newBuilder()
.setPlatform(Platform.all())
.setAudience(Audience.alias(request.getRecipient()))
.setNotification(Notification.newBuilder()
.setAlert(request.getTitle())
.addAndroidNotification(request.getTitle(), request.getContent(), null)
.addIosNotification(request.getTitle(), request.getContent())
.build())
.build();
PushResult result = jpushClient.sendPush(payload);
return result.getStatusCode() == 200;
} catch (Exception e) {
log.error("推送发送失败: {}", e.getMessage());
return false;
}
}
@Override
public ChannelType getType() {
return ChannelType.PUSH;
}
}
📊 各渠道适配器对比
🧩 适配器工厂与统一调用
// 适配器工厂 - 统一管理所有渠道适配器
@Component
public class NotificationAdapterFactory {
private final Map<ChannelType, INotificationChannel> adapterMap = new HashMap<>();
public NotificationAdapterFactory(
EmailAdapter emailAdapter,
SmsAdapter smsAdapter,
PushAdapter pushAdapter) {
adapterMap.put(ChannelType.EMAIL, emailAdapter);
adapterMap.put(ChannelType.SMS, smsAdapter);
adapterMap.put(ChannelType.PUSH, pushAdapter);
}
public INotificationChannel getAdapter(ChannelType type) {
INotificationChannel adapter = adapterMap.get(type);
if (adapter == null) {
throw new IllegalArgumentException("不支持的渠道类型: " + type);
}
return adapter;
}
}
// 业务层统一调用
@Service
public class NotificationService {
@Autowired
private NotificationAdapterFactory adapterFactory;
public boolean sendNotification(NotificationRequest request) {
INotificationChannel adapter = adapterFactory.getAdapter(request.getChannelType());
return adapter.send(request);
}
}
💡 设计要点总结
- 每个渠道适配器只负责协议转换,不包含业务逻辑
- 适配器内部可加入重试、熔断、日志等横切关注点
- 新增渠道(如模板消息)只需新增一个Adapter实现类
- 适配器模式让通知系统具备良好的扩展性和可维护性
✨ 专注课程资料整理