Unchanged contract and caller
interface Sender {
send(message: string): boolean
}
class EmailSender implements Sender {
send(message: string): boolean {
return emailApi.send(message)
}
}
class NotificationDispatcher {
constructor(private senders: ReadonlyMap<string, Sender>) {}
send(message: string, channel: string): boolean {
const sender = this.senders.get(channel)
if (!sender) throw new Error('Unknown channel: ' + channel)
return sender.send(message)
}
}
Email only
const senders = new Map<string, Sender>([
['email', new EmailSender()],
])
const dispatcher = new NotificationDispatcher(senders)
dispatcher.send('Order shipped', 'email')
The dispatcher receives the email provider’s acceptance result.
Email and push
class PushNotificationSender implements Sender {
send(message: string): boolean {
return pushApi.send(message)
}
}
const senders = new Map<string, Sender>([
['email', new EmailSender()],
['push', new PushNotificationSender()],
])
const dispatcher = new NotificationDispatcher(senders)
dispatcher.send('Order shipped', 'email')
dispatcher.send('Order shipped', 'push')
The same dispatcher receives the push provider’s acceptance result.