Factory Method
To me this just seem to be a band-aid fix for OOP shortcomings.
Look at this example found on geekforgeeks:
Groovy
interface Notification {
void notifyUser()
}
class SMSNotification implements Notification {
@Override
void notifyUser() {
System.out.println("Sending an SMS notification")
}
}
class EmailNotification implements Notification {
@Override
void notifyUser() {
System.out.println("Sending an e-mail notification")
}
}
class PushNotification implements Notification {
@Override
void notifyUser() {
System.out.println("Sending a push notification")
}
}
class NotificationFactory {
Notification createNotification(String channel) {
if (channel == null || channel.isEmpty())
return null
switch (channel) {
case "SMS":
return new SMSNotification()
case "EMAIL":
return new EmailNotification()
case "PUSH":
return new PushNotification()
default:
throw new IllegalArgumentException("Unknown channel "+channel)
}
}
}
class NotificationService {
static void main(String[] args) {
NotificationFactory notificationFactory = new NotificationFactory()
Notification notification = notificationFactory.createNotification("SMS")
notification.notifyUser()
}
}
How is this any better than:
Clojure
(defmulti notify-user identity)
(defmethod notify-user :sms [_]
(print "Sending a SMS notification."))
(defmethod notify-user :email [_]
(print "Sending an e-mail notification."))
(defmethod notify-user :push [_]
(print "Sending a push notification."))
(defmethod notify-user :default [channel]
(throw (IllegalArgumentException. (str "Unknown channel " channel))))
(notify-user :sms)
There are several other ways of doing that in Clojure, but I my go to would be multi-methods because all the cases are clearly separated. That's 50 lines of Groovy/Java vs 15 in Clojure.
Another advantage is that people consuming libraries with multi-methods can extend them by providing a new implementation:
Clojure
(defmethod notify-user :vr-headset []
(print "Sending an annoying notification to the VR headset."))
With Factory Method every time you add a new implementation you have to change the factory to include this new implementation.