- แนวคิด
- โครงสร้าง
- Workshop: สร้าง UI Components ข้ามแพลตฟอร์ม
- เปรียบเทียบกับ Factory Method
- ข้อดีและข้อควรระวัง
- แนวทางต่อยอด
- สรุป
#แนวคิด
Abstract Factory เป็น Creational Design Pattern สำหรับสร้างชุดออบเจ็กต์ที่เกี่ยวข้องกัน (family of related products) โดยไม่ต้องระบุคลาสที่เป็นรูปธรรมในโค้ดฝั่งผู้ใช้งาน เหมาะเมื่อระบบต้องสลับชุดผลิตภัณฑ์ เช่น UI แบบ Windows และ macOS โดยยังคงใช้ API เดียวกัน
#โครงสร้าง
- Abstract Products:
Button,Checkboxกำหนดพฤติกรรมร่วม - Concrete Products:
WindowsButton,MacButton,WindowsCheckbox,MacCheckbox - Abstract Factory:
GUIFactoryกำหนดเมธอดสร้างผลิตภัณฑ์ - Concrete Factories:
WindowsFactory,MacFactoryสร้างผลิตภัณฑ์ที่เข้าชุดกัน - Client:
Applicationใช้งานผ่าน interface โดยไม่ผูกกับคลาสจริง
classDiagram
class GUIFactory {
<<interface>>
+createButton() Button
+createCheckbox() Checkbox
}
class WindowsFactory
class MacFactory
GUIFactory <|.. WindowsFactory
GUIFactory <|.. MacFactory
class Button { <<interface>> +render() void }
class Checkbox { <<interface>> +render() void }
class WindowsButton
class MacButton
class WindowsCheckbox
class MacCheckbox
Button <|.. WindowsButton
Button <|.. MacButton
Checkbox <|.. WindowsCheckbox
Checkbox <|.. MacCheckbox
WindowsFactory ..> WindowsButton : creates
WindowsFactory ..> WindowsCheckbox : creates
MacFactory ..> MacButton : creates
MacFactory ..> MacCheckbox : creates
#Workshop: สร้าง UI Components ข้ามแพลตฟอร์ม
ใช้ Java 17+ สร้างไฟล์ Main.java:
interface Button {
void render();
}
interface Checkbox {
void render();
}
class WindowsButton implements Button {
public void render() {
System.out.println("Render Windows button");
}
}
class MacButton implements Button {
public void render() {
System.out.println("Render macOS button");
}
}
class WindowsCheckbox implements Checkbox {
public void render() {
System.out.println("Render Windows checkbox");
}
}
class MacCheckbox implements Checkbox {
public void render() {
System.out.println("Render macOS checkbox");
}
}
interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
class WindowsFactory implements GUIFactory {
public Button createButton() {
return new WindowsButton();
}
public Checkbox createCheckbox() {
return new WindowsCheckbox();
}
}
class MacFactory implements GUIFactory {
public Button createButton() {
return new MacButton();
}
public Checkbox createCheckbox() {
return new MacCheckbox();
}
}
class Application {
private final Button button;
private final Checkbox checkbox;
Application(GUIFactory factory) {
this.button = factory.createButton();
this.checkbox = factory.createCheckbox();
}
void render() {
button.render();
checkbox.render();
}
}
public class Main {
public static void main(String[] args) {
String platform = args.length > 0 ? args[0] : "windows";
GUIFactory factory = switch (platform.toLowerCase()) {
case "windows" -> new WindowsFactory();
case "mac" -> new MacFactory();
default -> throw new IllegalArgumentException("Unsupported platform: " + platform);
};
new Application(factory).render();
}
}
#ทดลองรัน
javac Main.java
java Main windows
# Render Windows button
# Render Windows checkbox
java Main mac
# Render macOS button
# Render macOS checkbox
#เปรียบเทียบกับ Factory Method
| ประเด็น | Factory Method | Abstract Factory |
|---|---|---|
| จุดประสงค์ | กำหนดจุดสร้างผลิตภัณฑ์ผ่านเมธอด | สร้างชุดผลิตภัณฑ์ที่สัมพันธ์กัน |
| รูปแบบ | มักใช้ inheritance เพื่อเปลี่ยนชนิดผลิตภัณฑ์ | มักใช้ composition ผ่าน factory interface |
| ตัวอย่าง | สร้างปุ่มชนิดหนึ่ง | สร้างปุ่มและ checkbox ให้เข้าธีมเดียวกัน |
#ข้อดีและข้อควรระวัง
ข้อดี: ลดการผูกติดกับคลาสจริง, สลับ family ได้ง่าย, ป้องกันการผสมผลิตภัณฑ์ต่างชุดโดยไม่ตั้งใจ, สนับสนุน Dependency Inversion Principle
ข้อควรระวัง: เพิ่ม interface และคลาสจำนวนมาก และหากเพิ่มชนิดผลิตภัณฑ์ใหม่ เช่น Slider ต้องแก้ factory interface และ concrete factories ทุกตัว
#แนวทางต่อยอด
- เพิ่ม
LinuxFactoryพร้อมผลิตภัณฑ์LinuxButtonและLinuxCheckbox - เขียน JUnit 5 tests ตรวจสอบว่าแต่ละ factory คืนผลิตภัณฑ์ถูก family
- เชื่อม factory กับ dependency injection เพื่อเลือกแพลตฟอร์มจาก configuration
#สรุป
Abstract Factory เหมาะเมื่อแอปพลิเคชันต้องสร้าง หลายผลิตภัณฑ์ที่ต้องเข้าชุดกัน และต้องการแยกโค้ดธุรกิจออกจากรายละเอียดการสร้างออบเจ็กต์ แต่ถ้าสร้างเพียงผลิตภัณฑ์ชนิดเดียว Factory Method หรือ simple factory อาจเรียบง่ายกว่า