java - 用于转换 Java 对象字段的设计模式
问题描述
我有一堂课:
@Getter
@Setter
public class Message {
private String sender;
private Set<String> receivers;
private String text;
}
该类Message
可以通过EmailMessage
并SMSMessage
具有自己的附加字段进行扩展。
有 2 种服务 - EmailService 和 SMSService。它们都执行以下操作:
- 获取包含发送者和接收者用户 ID 的消息对象。
- EmailService 调用另一个服务来将用户 ID 转换为电子邮件 ID。SMSService 也将用户 ID 转换为电话号码。
- Message 对象应在其各自的服务中转换为 EmailMessage 和 SMSSMEssage。
- 发送 EmailMessage 和 SMSMessage。
我一直在经历许多设计模式来解决这个问题。但是我没有找到任何这样的模式来转换对象的字段和/或将父对象转换为子对象。
唯一接近的设计模式是策略和装饰器。
我正在使用策略模式在运行时使用 EmailService 或 SMSService。它只是解决了我问题的一部分。装饰器模式是否有助于解决其他问题?
编辑:添加当前实现
public abstract class AbstractMessageService<T extends Message> {
@KafkaHandler(isDefault = true)
public final void consume(Message message) {
T convertedMessage = getMessageConverterStrategy().convert(message);
send(convertedNotificationMessage);
}
protected abstract void send(T message) throws Exception;
protected abstract MessageConverterStrategy getMessageConverterStrategy();
}
@KafkaListener(
topics = "topicName",
groupId = "email-group")
public class EmailService extends AbstractMessageService<EmailMessage> {
@Override
protected void send(EmailMessage message) {
// Some logic to send email.
}
@Override
protected MessageConverterStrategy getMessageConverterStrategy() {
return new EmailMessageConverterStrategy();
}
}
@KafkaListener(
topics = "topicName",
groupId = "sms-group")
public class SMSService extends AbstractMessageService<SMSMessage> {
@Override
protected void send(SMSMessage message) {
// Some logic to send sms.
}
@Override
protected MessageConverterStrategy getMessageConverterStrategy() {
return new SMSMessageConverterStrategy();
}
}
public interface MessageConverterStrategy<T extends Message> {
T convert(Message message);
}
在 SMSMessageConverterStrategy 和 EmailMessageConverterStrategy 中,我想使用其他设计模式分别将 Message 转换为 SMSMessage 和 EmailMessage。
解决方案
因为你必须转换几乎所有东西,我认为Message
和Email
和SMS
不相关。我认为你应该使用这样的工厂方法:
public class Test {
public static void main(String[] args) throws Exception {
Message m = new Message();
Email email = Email.from(m);
EmailService.sendMail(email);
}
}
class Message {
private String sender;
private Set<String> receivers;
private String text;
}
class Email {
private String senderMailId;
private String text;
private Set<String> receiverMailIds;
//make it private
private Email() {
}
public static Email from(Message m) {
Email email = new Email();
email.senderMailId = ""; //call MappingService.toEmailId(m.getSender());
//do rest of the conversion and processing
return email;
}
}
class EmailService {
public static void sendMail(Email e) {
//send the mail
}
}
推荐阅读
- ios - 当这个控制器在故事板中时,如何通过类名初始化控制器?
- vba - 通过 MS-Word 打开 pdf 文件
- java - 如何在测试中@Autowired BuildProperties?
- php - 从 MySQL 数据库填充文本框/下拉列表
- java - 使用 ignite 集群时如何处理严重故障?
- html - appdesigner 列表框项目无法识别 HTML 标记
- jquery - 下拉子菜单保持打开状态
- node.js - SocketIO:如何在单个请求中发出事件
- java - DynamoDB 异常元素与架构不匹配
- ruby-on-rails - 如何将 id 传递给控制器中的操作 - Ruby on Rails