1. Mẫu đơn giản nhà máy (Simple Factory)
Mẫu đơn giản nhà máy không thuộc danh sách 23 mẫu thiết kế GoF nhưng thường được dùng làm nền tảng để hiểu các mẫu nhà máy phức tạp hơn. Nó định nghĩa một lớp nhà máy chịu trách nhiệm tạo ra các đối tượng dựa trên tham số đầu vào, với các đối tượng được tạo ra đều kế thừa từ một lớp cha chung.
Thực thi mẫu
Lớp sản phẩm chung:
public abstract class Chart {
protected float[] values;
public Chart(float[] values) {
this.values = values;
System.out.println("Thiết lập tham số chung...");
}
public void setValues(float[] values) {
this.values = values;
}
public abstract void render();
}
Lớp sản phẩm cụ thể (ví dụ):
public class LineChart extends Chart {
public LineChart(float[] values) {
super(values);
System.out.println("Khởi tạo LineChart");
}
@Override
public void render() {
System.out.println("Hiển thị dữ liệu dưới dạng đường thẳng");
}
}
Lớp nhà máy:
public class ChartFactory {
public static final int LINE = 0;
public static final int BAR = 1;
public static final int PIE = 2;
public static Chart createChart(int type) {
switch (type) {
case BAR: return new BarChart();
case PIE: return new PieChart();
default: return new LineChart();
}
}
}
Thử nghiệm:
Chart chart = ChartFactory.createChart(ChartFactory.LINE);
chart.setValues(new float[]{5, 10, 15});
chart.render();
Kết quả:
Thiết lập tham số chung...
Khởi tạo LineChart
Hiển thị dữ liệu dưới dạng đường thẳng
2. Mẫu phương pháp nhà máy (Factory Method)
Mẫu phương pháp nhà máy định nghĩa một giao diện tạo đối tượng, để lớp con quyết định tạo ra loại đối tượng nào. Nó trì hoãn việc khởi tạo đối tượng đến lớp con, thuộc nhóm mẫu tạo đối tượng (Creational Pattern).
Vấn đề với mẫu đơn giản
Khi thêm sản phẩm mới, lớp nhà máy cần chỉnh sửa mã nguồn (thêm case vào switch). Điều này vi phạm nguyên tắc mở-đóng (Open/Closed Principle). Ví dụ: khi thêm loại biểu đồ mới, phải sửa lại ChartFactory.
Giải pháp
Áp dụng mẫu phương pháp nhà máy:
public interface LogHandler {
void log();
}
public interface LogFactory {
LogHandler createHandler();
}
Thực thi:
public class DatabaseLog implements LogHandler {
@Override
public void log() {
System.out.println("Ghi log vào cơ sở dữ liệu");
}
}
public class DatabaseFactory implements LogFactory {
@Override
public LogHandler createHandler() {
return new DatabaseLog();
}
}
Cấu hình động:
public class ConfigLoader {
public static Object loadBean(String beanName) {
// Xử lý XML cấu hình
// Thay đổi cấu trúc XML và logic parse
}
}
Cấu hình XML:
<config>
<logFactory>factory.DatabaseFactory</logFactory>
</config>
Thử nghiệm:
LogFactory factory = (LogFactory) ConfigLoader.loadBean("logFactory");
factory.createHandler().log();
Kết quả:
Ghi log vào cơ sở dữ liệu