Fabryka jest wzorcem kreacyjnym, którego celem jest ułatwienie tworzenia obiektów tego samego typu bez specyfikowania ich klas. Przykładowo jest przydatne w grach strategicznych, gdzie jeden budynek (fabryka) produkuje kilka typów jednostek z różnymi zmiennymi.
Ogólna struktura tego wzorca wygląda następująco:

W praktyce załóżmy, że mamy aplikację „symulującą” dwie restauracje: jedna serwująca burgera XXL i napój L, a druga burgera L i napój XXL w różnych cenach. Bez zastosowania tego wzorca mogłaby ona wyglądać tak:
public class Main {
public static void main(String[] args) {
Dish burger1 = new Burger(20, "XXL");
Dish soda1 = new Soda(5, "L");
Dish burger2 = new Burger(15, "L");
Dish soda2 = new Soda(10, "XXL");
}
}
public abstract class Dish {
private int price;
private String size;
public Dish(int price, String size) {
this.price = price;
this.size = size;
}
}
public class Burger extends Dish{
public Burger(int price, String size) {
super(price, size);
}
}
public class Soda extends Dish{
public Soda(int price, String size) {
super(price, size);
}
}
W takim przypadku trzeba zawsze pamiętać, która restauracja jakie serwuje obiekty. Po zastosowaniu wzorca fabryka program mógłby prezentować się w taki sposób:
import dishes.*;
public class Main {
public static void main(String[] args) {
Restaurant leftRestaurant = new LeftRestaurant();
Restaurant rightRestaurant = new RightRestaurant();
Dish leftBurger = leftRestaurant.createBurger();
Dish leftSoda = leftRestaurant.createSoda();
Dish rightBurger = rightRestaurant.createBurger();
Dish rightSoda = rightRestaurant.createSoda();
}
}
package dishes;
public abstract class Dish {
private int price;
private String size;
public Dish(int price, String size) {
this.price = price;
this.size = size;
}
}
package dishes;
public class Burger extends Dish{
public Burger(int price, String size) {
super(price, size);
}
}
package dishes;
public class Soda extends Dish{
public Soda(int price, String size) {
super(price, size);
}
}
package dishes;
public abstract class Restaurant {
public abstract Dish createBurger();
public abstract Dish createSoda();
}
package dishes;
public class LeftRestaurant extends Restaurant{
@Override
public Dish createBurger() {
return new Burger(20, "XXL");
}
@Override
public Dish createSoda() {
return new Soda(5, "L");
}
}
package dishes;
public class RightRestaurant extends Restaurant{
@Override
public Dish createBurger() {
return new Burger(15, "L");
}
@Override
public Dish createSoda() {
return new Soda(10, "XXL");
}
}
W tym konkretnym przypadku wzorzec fabryka dorobił trochę kodu, ale jednocześnie go uprościł. W bardziej rozbudowanych aplikacjach zmiana ta jest diametralna.
Niestety największą wadą tego wzorca jest to, że za każdym razem jak chcemy dodać nową fabrykę lub produkty to musimy ingerować w większość poprzednich klas.