Enum’ları Factory olarak kullanabilir miyiz?
Medium’a giriş yaptığım ilk yazımda, tecrübe ettiğim Factory Pattern’i örneklendirerek aktarmak ve enum’ları kullanarak nasıl daha yalın hale getirebileceğimizden bahsetmek istedim.
Öncelikle gereksinimden bahsetmek gerekirse; kullanıcıların gerçekleştirdiği event’lere göre aksiyonların belirlenmesi ve tanımlanan aksiyonlara göre de kullanıcılarla farklı bildirim yöntemleri (sms, e-posta, push ya da farklı bir servis çağırımı yamak gibi) ile iletişim kurmak olarak özetleyebiliriz.
Başlangıç olarak geliştirmeyi aşağıdaki adımları takip ederek ilerletebiliriz:
- Interface içinde factory method tanımlanması
- Subclass’ların yukarıdaki factory method’u implemente etmesi
- Hangi object’in yaratılacağına karar verilmesi
Class Diagram
Action interface
public interface Action {
void sendActionToUser();
}
Implemented Classes
public class SmsAction implements Action{
@Override
public void sendActionToUser() {
//TODO : develop business logic
System.out.println("Sending Sms action");
}
}
public class EmailAction implements Action{
@Override
public void sendActionToUser() {
//TODO : develop business logic
System.out.println("Sending Email action");
}
}
public class PushNotificationAction implements Action{
@Override
public void sendActionToUser() {
//TODO : develop business logic
System.out.println("Sending Push notification action");
}
}
Factory Class
public class ActionFactory {
public Action createAction (String actionType){
switch (actionType) {
case "SMS":
return new SmsAction();
case "EMAIL":
return new EmailAction();
case "PUSH":
return new PushNotificationAction();
default:
throw new IllegalArgumentException("Unknown action type "+ actionType);
}
}
}
Action Service
public class ActionService {
public static void main(String[] args)
{
ActionFactory actionFactory = new ActionFactory();
Action action = actionFactory.createAction("SMS");
action.sendActionToUser();
}
}
Uygulanan Yöntemin Dezavantajları
- Logic basit olmasına rağmen condition kullanımı kolaylıkla bazı durumları gözden kaçırmamıza sebep olabilir.
- String constant kullanımı daha sonra bu geliştirme üzerinde çalışacak arkadaşların createAction metodunu kullanmadan önce izin verilen actionType’ları nerede arayacaklarını belirleyebilmek adına tüm kodu gözden geçirmelerine zorlayabilir.
- Yeni bir action implementation’ı için gerektiğinden fazla yerde kod değişikliğine sebep olabilir.
Daha effective bir yol var mı?
Yukarıda bahsettiğim dezavantajlardan kurtulmanın yolu java’nın bize sunduğu enum’ları kullanmak diyebiliriz.
Aşağıda nasıl implemente edebileceğimize göz atabilirsiniz.
Create enum as factories
public enum ActionType {
SMS("SMS") {
@Override
public Action createAction() {
return new SmsAction();
}
},
EMAIL("EMAIL") {
@Override
public Action createAction() {
return new EmailAction();
}
},
PUSH("PUSH") {
@Override
public Action createAction() {
return new PushNotificationAction();
}
};
public abstract Action createAction();
private final String actionTypeName;
ActionType(String actionTypeName) {
this.actionTypeName = actionTypeName;
}
public String getActionTypeName() {
return actionTypeName;
}
public static ActionType getEnumByString(String name) {
for (ActionType a : ActionType.values()) {
if (a.actionTypeName.equalsIgnoreCase(name))
return a;
}
return null;
}
}
Action Service
public class ActionService {
public static void main(String[] args)
{
ActionType actionType = ActionType.getEnumByString("SMS");
actionType.createAction().sendActionToUser();
}
}
Sonuç
Java’nın bize sunduğu enum’ları factory olarak kullanmak basit ve etkili bir yöntem diyebiliriz. Devam eden bakım ve geliştirme maliyetini düşürmenin yanında, bu yöntem aynı kod parçacığında daha sonra geliştirme yapacak arkadaşların işini kolaylaştırmaktadır.