问题主要是一个设计问题(与ddd有点相关)。对不起,关于这个人为的例子:从同一基类的域类中调用不同的服务
假设,你有(域)类表示不同类型的水果:苹果,樱桃等。现在假设你必须实施一些压制果汁的行为。呼叫者应该能够在不知道他得到哪个特定水果的情况下调用挤压。
我应该把这种行为放在哪里?
当然,一个可以定义一个水果接口/基类的功能
Fruit#squeeze()
,并让所有子类实现自己的行为。 现在主叫方可以简单地做这样的事情:
Fruit f = new Cherry();
f.squeeze();
但如果挤不那么简单,涉及到更复杂的行为就像调用不同的外部服务,为每一个水果不同的人喜欢
应该做什么AppleJuicerService#squeeze(Apple a)
和
CherryJuicerService#squeeze(Cherry c)
?从域类调用服务感觉不对。
我读过关于双调度模式,似乎不适合在这里,因为每个子类都需要不同的服务。
我的问题是:在这里可以做些什么来获得“干净”的设计?
编辑:
感谢您的答案为止。我会尽量澄清这个问题。我将尝试给出另一个希望较少人为的问题,例如我试图在此处陈述的问题:
考虑允许将其内容显示为字符串的消息基类。
interface Message {
String showContent();
}
现在假设我们有不同类型的消息等的EMailMessage:
class EMailMessage implements Message {
//some specific parameters for email
private EmailAddress recipientEmail;
public String showContent() {
//here the content would be converted to string
return "the content of an EMail"
}
}
另一种类型的将是一个SMSMessage:
class SMSMessage implement SMSMessage {
//some specific parameters for SMS
private TelNumber recepientTelephoneNumber;
public String showContent() {
//here the content would be converted to string
return "the content of a SMS"
}
}
另外假设,消息被建模为实体,并且因此可以保存在数据库中。尽管在技术上很有意思,但假设像Spring这样的一些依赖注入框架被用来注入依赖关系。
类似于水果的例子,考虑我们必须实现发送消息给收件人的send()行为。此外,假设发送电子邮件涉及与SMS不同的逻辑。现在,问题是:应该在哪里发送发送消息的逻辑?
通常我会选择创建一个用于发送SMS的服务,例如将封装例如SMS服务提供商的API。此外,我会创建另一个服务来封装发送电子邮件。
interface SendMessageService<T extends Message> {
void send(T message);
}
class SendEmailService extends SendMessageService<EMailMessage> {
public void send(EMailMessage message) {
//send the EMail
}
}
class SendSMSService extends SendMessageService<SMSMessage> {
public void send(SMSMessage message) {
//send the SMS
}
}
这种方法的缺点是,你不能没有确定它的具体子类,即像下面发送一条消息不能直接
List<Message> messages = //Messages of different types
SendMessageService service = //???
for (Message m : messages) {
service.send(m);
}
当然人们可以创建服务创建工厂根据消息的具体类型。但是这有点意味着克隆Message的继承层次结构。有没有更好的方法来达到预期的效果?或者我错过了什么?或者,以某种方式将服务注入实体会更好吗?
也许这个例子在这里做得太过分了 - Fruit#squeeze()有一个void返回类型,它对Fruit有什么作用? –
+1如果您不解释“挤压”可能代表什么以及为什么首先需要服务,我们无法提供一个好的答案。 (顺便说一句,从一个实体中调用域服务是完全合法的,即使你会更频繁地看到它) – guillaume31
@ guillaume31我试图编辑问题以进一步解释问题 – John