The question is mostly a design question (somewhat related to ddd). Sorry about the contrived example:
Assume, you have (domain) classes representing different types of fruits: apple, cherry and so on. Now suppose you have to implement some behavior of pressing out the juice. A caller should be able to invoke squeezing without knowing which specific fruit he's got.
Where should I put this behavior?
Surely, one could define a fruit interface / base class function
Fruit#squeeze()
and let all subclasses implement their own behavior. Now a caller could simply do something like this:
Fruit f = new Cherry();
f.squeeze();
But what should be done if squeezing isn't as simple and involves more complex behavior like calling different external services, for each a fruit a different one like
AppleJuicerService#squeeze(Apple a)
and
CherryJuicerService#squeeze(Cherry c)
? It feels wrong to call services from a domain class.
I've read about the double dispatch pattern which seems not to fit here, as every subclass needs a different service.
My question would be: What can be done here to get a "clean" design?
EDIT:
Thanks for all your answers so far. I'll try to clarify the problem a bit. I'll try to give another, hopefully less contrived example for the problem I'm trying to state here:
Consider a Message base class which allows to show its content as a String.
interface Message {
String showContent();
}
Now suppose we have different types of messages like an 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"
}
}
Another type would be an 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"
}
}
Furthermore suppose, Messages are modeled as Entities and therefore can be persisted in a database. Though quite technically, assume that some Dependency Injection Framework like Spring is used to inject dependencies.
In analogy to the fruit example, consider we have to implement a send() behaviour which sends the Message to the recipient. Furthermore, assume that sending an EMail involves different logic than an SMS. Now, the question: Where should one put the logic of sending a Message?
Usually I'd opt to create a service for sending an SMS for example which would encapsulate e.g. the API of an SMS service provider. Furthermore, I'd create another service to encapsulate sending an EMail.
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
}
}
The drawback of this approach is that you cannot send a Message without determining its concrete subclass, i.e. something like the following is not directly possible
List<Message> messages = //Messages of different types
SendMessageService service = //???
for (Message m : messages) {
service.send(m);
}
Surely one could create a factory for creating Services according to the specific type of message. But that somewhat means cloning the inheritance hierarchy of Message. Is there some better way to achieve the desired result? Or am I missing something? Or would it be better to somehow inject the service into the entity?
squeezecould possibly stand for and why you need a service in the first place. (BTW, it is perfectly legal to call a Domain Service from an Entity even though you'll see it the other way around more often) - guillaume31