This article is lecture note from "Head First Design Patterns" by Elisabeth Freeman and Kathy Sierra and CS course from Kookmin by Inkyu Kim
The Factory Method Pattern defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
The Product declares the interface, which is common to all objects that can be produced by the creator and its subclasses.
Concrete Products are different implementations of the product interface. The Creator class declares the factory method that returns new product objects. It's important that the return type of this method matches the product interface. We can declare the factory method as abstract to force all subclasses to implement their own versions of the method. As an alternative, the base factory method can return some default product type.
Concrete Creators override the base factory method so it returns a different type of product. Note that the factory method doesn't have to create new instances all the time. It can also return existing objects from a cache, an object pool, or another source.
<PizzaStore.java>
public abstract class PizzaStore {
abstract Pizza createPizza(String item);
public Pizza orderPizza(String type) {
Pizza pizza = createPizza(type);
System.out.println("--- Making a " + pizza.getName() + " ---");
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
This is our abstract creator class. It defines an abstract factory method that the subclasses implement to produce products. Often the creator contains code that depends on an abstract product, which is produced by a subclass. The creator never really knows which concrete product was produced.
Let's look at our product.
<Pizza.java>
import java.util.ArrayList;
public abstract class Pizza {
String name;
String dough;
String sauce;
ArrayList<String> toppings = new ArrayList<String>();
void prepare() {
System.out.println("Prepare " + name);
System.out.println("Tossing dough...");
System.out.println("Adding sauce...");
System.out.println("Adding toppings: ");
for (String topping : toppings) {
System.out.println(" " + topping);
}
}
void bake() {
System.out.println("Bake for 25 minutes at 350");
}
void cut() {
System.out.println("Cut the pizza into diagonal slices");
}
void box() {
System.out.println("Place pizza in official PizzaStore box");
}
public String getName() {
return name;
}
public String toString() {
//code here
}
return display.toString();
}
}
Then here is one of our concrete creator, NewYork style pizza store~
<NYPizzaStore.java>
public class NYPizzaStore extends PizzaStore {
Pizza createPizza(String item) {
if (item.equals("cheese")) {
return new NYStyleCheesePizza();
} else if (item.equals("veggie")) {
return new NYStyleVeggiePizza();
} else if (item.equals("clam")) {
return new NYStyleClamPizza();
} else if (item.equals("pepperoni")) {
return new NYStylePepperoniPizza();
} else return null;
}
}
The createPizza()
method is our factory method. It produces products.
<NYStyleCheesePizza.java>
public class NYStyleCheesePizza extends Pizza {
public NYStyleCheesePizza() {
name = "NY Style Sauce and Cheese Pizza";
dough = "Thin Crust Dough";
sauce = "Marinara Sauce";
toppings.add("Grated Reggiano Cheese");
}
}
<PizzaTestDrive.java>
public static void main(String[] args) {
PizzaStore nyStore = new NYPizzaStore();
PizzaStore chicagoStore = new ChicagoPizzaStore();
Pizza pizza = nyStore.orderPizza("cheese");
System.out.println("Ethan ordered a " + pizza.getName() + "\n");
pizza = chicagoStore.orderPizza("cheese");
System.out.println("Joel ordered a " + pizza.getName() + "\n");
// other codes here
}
}
The Product classes and Creator classes both have abstract classes that are extended by concrete creators which know about specific implementation for each concrete products.
The Factory Method is useful when you don't know the exact types and dependencies of the objects your code should work with. This pattern separates product construction code from the code that actually usees the product. Therefore it's easier to extend the product construction code independently from the rest of the code.
Secondly, it is used when you want to provide users of your library of framework with a way to extend its internal components. Inheritance is probably the easiest way to extend the default behaviour of a library or framework. But how would the framework recognise that your subclass should be used instead of a standard component?
The Solution is to reduce the code that constructs components across the framework into a single factory method and let anyone override this method in addition to extending the component itself.
For example, imagine that you write an ap using an open source UI framework. Your app should have round buttons, but the framework only provides square ones. You extend the standard Button
class with a glorious RoundButton
subclass. But now you need to tell the main UIFramework
class to use the new button subclass instead of a default one.
To achieve this, you create a subclass UIWithRoundButtons
from a base framework class and override its createButton
method. While this method returns Button
objects in the base class, you make your subclass return RoundButton
objects. Now use the UIWithRoundButtons
class instead of UIFramework
.
By using Factory Method you avoid tight coupling between the creator adn the concrete products. Also, you can achieve Single Responsibility Principle. You can move the product creation code into one place in the program, making the code easier to support. Last, Open Closed Principle. You can introduce new types of products into the program without breaking existing client code.
Découvrez la grandeur de hawa expo 2024, la vitrine ultime du mobilier vietnamien du 6 au 9 mars au Centre des congrès et des expositions de Saigon, à Hô Chi Minh-Ville. Au-delà d'une exposition, c'est une vitrine puissante d'une industrie en plein essor. Avec 700 exposants, ce salon sur le thème du vintage célèbre le dynamisme et la diversité du secteur du meuble vietnamien. Plongez dans l'innovation et le style, marquant un événement incontournable pour les amateurs de meubles et les professionnels de l'industrie.