Factory tách "tạo object" khỏi "dùng object". Caller không gọi new ConcreteClass() mà gọi factory; factory quyết định trả về concrete nào.
Vì sao cần: thay implementation, ẩn complexity, cache/pool, dễ test (mock factory).
3 biến thể chính:
1. Simple Factory:
class ShapeFactory {
static Shape create(String type) {
return switch (type) {
case "circle" -> new Circle();
case "square" -> new Square();
default -> throw new IllegalArgumentException();
};
}
}**2.
Factory Method (GoF):** subclass quyết định concrete class.
abstract class Dialog {
public void render() { createButton().onClick(); }
protected abstract Button createButton();
}
class MacDialog extends Dialog {
protected Button createButton() { return new MacButton(); }
}3. Abstract Factory (GoF): factory tạo họ object liên quan (UI theme: button + checkbox cùng style).
Static factory method trên class (hiện đại, ưa chuộng): LocalDate.now(), List.of(...), Optional.empty(), Integer.valueOf(5) (có cache cho -128..127).
Khi không dùng:
- Class đơn giản, 1 cách tạo → new thẳng. Đừng over-engineer.
- Có DI framework (Spring) — container đã là factory siêu cấp.
Factory là nền tảng cho Dependency Injection — caller phụ thuộc interface, không phụ thuộc concrete.
Factory separates "creating objects" from "using objects". Callers do not call new ConcreteClass(); they ask a factory which decides what to return.
Why use it: swap implementations, hide complexity, caching/pooling, easier testing.
Three main variants:
1. Simple Factory:
class ShapeFactory {
static Shape create(String type) {
return switch (type) {
case "circle" -> new Circle();
case "square" -> new Square();
default -> throw new IllegalArgumentException();
};
}
}**2.
Factory Method (GoF):** subclasses decide the concrete class.
abstract class Dialog {
public void render() { createButton().onClick(); }
protected abstract Button createButton();
}
class MacDialog extends Dialog {
protected Button createButton() { return new MacButton(); }
}3. Abstract Factory (GoF): factory creating families of related objects (UI theme: button + checkbox of the same style).
Static factory methods on the class (modern, preferred): LocalDate.now(), List.of(...), Optional.empty(), Integer.valueOf(5) (cached for -128..127).
When not to use:
- Simple class, one way to create → just use new. Avoid over-engineering.
- Have a DI framework (Spring) — the container is already a super-factory.
Factories underpin Dependency Injection — callers depend on interfaces, not concrete classes.