interface EncryptedMessage { ... } interface DecryptedMessage { ... } // domain service representing the HeadQuarter component in the system interface HeadQuarter { void send(DecryptedMessage decryptedMessage); } // domain service representing the CodeBreaker component in the system interface CodeBreaker { DecryptedMessage breakIt(EncryptedMessage encryptedMessage); } //the heart of our simple domain class EnemyMessageCatcher { private HeadQuarter headQuarter; private CodeBreaker codeBreaker; void captureDecryptAndForward(EncryptedMessage encryptedMessage) { DecryptedMessage decryptedMessage = codeBreaker.breakIt(encryptedMessage); headquarter.send(decryptedMessage); } //infrastructure layer class WSBasedHeadQuarter implements HeadQuarter { //calling some webservice } class WSBasedCodeBreaker implements CodeBreaker { //calling some webservice } }
Both the HeadQuarter and the CodeBreaker are domain services. Although our domain knows nothing about how these functionalities are implemented (whether they are in other physical components, or just in simple objects), it still knows about the concept, that there is a HeadQuarter who needs to be notified and there is a CodeBreaker that can decrypt the enemy's messages. That's why the interface(=concept) is in the Domain and the implementation(=the details) is in the infrastructure. Using Hexagonal Architecture-terminology, the domain service (interface) is the port, and the implementation is the adapter.
The DDD-savvy reader can notice, that the Repository pattern is actually an ordinary domain service. It represents the concept of storing and retrieving objects in the domain, and hides away how it's done exactly. I suppose the only reason for it being a separate pattern is simply that most application has to deal with persistence.