Factory Pattern
- Creates objects without specifying the exact class to create.
Lets say we have an Pizza Store and we need to sell different types of Pizza:
public class PizzaStore {
public Pizza orderPizza() {
Pizza pizza = new CheesePizza();
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
What happens when you need to sell more than one type of Pizza:
public Pizza orderPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")){
pizza = new CheesePizza();
} else if(type.equals("greek")){
pizza = new GreekPizza();
} else if(type.equals("pepperoni")){
pizza = new PepperoniPizza();
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
public interface Pizza {
void prepare();
void bake();
void cut();
void box();
}
public class CheesePizza implements Pizza {
public void prepare() {
//get cheese
//get parmesan
}
void bake() {
//melt cheese
}
}
public class VegetarianPizza implements Pizza {
public void prepare() {
//get tomato
//get egg mayo
}
void bake() {
//chop tomato
}
}
Pizza cheesePizza = new CheesePizza();
Pizza veggiePizza = new VegetarianPizza();
What is the problem?
- Code is not closed for modification, if we need to add more pizza, we need to modify the PizzaShop
How do we solve it?
- Move the object creations (new CheesePizza(), new PepperoniPizza()) out of the orderPizza method().
- Place it in something called a Factory
public PizzaFactory {
public static Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")){
pizza = new CheesePizza();
} else if(type.equals("greek")){
pizza = new GreekPizza();
} else if(type.equals("pepperoni")){
pizza = new PepperoniPizza();
} else if(type.equals("vegetarian")){ //Easily add new Pizza
pizza = new VeggiePizza();
}
return pizza;
}
}
How does the PizzaStore looks like now?
public class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza = PizzaFactory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
What is the advantage of this pattern?
- Now we only need to make modification in the PizzaFactory when implementation changes
- We can reuse this Factory in a different class eg: HomeDelivery
In a real case scenario we can use it for creating different type of NotificationService:
public interface NotificationService {
boolean send(Message message);
}
public class EmailNotificationService implements NotificationService {
boolean send(Message message) {
//Implementation
//SMTP SERVER GMAIL
}
}
public class SMSNotificationService implements NotificationService {
boolean send(Message message) {
//Implementation
//TWILIO WHISPIR
}
}
Factory:
public class NotificationFactory {
public static createNotificationService(String type) {
if (type.equals("EMAIL")){
return new EmailNotificationService();
} else if(type.equals("SMS")){
return new SMSService();
} else {
throw IllegalArgumentException();
}
}
}