- Factory Method คืออะไร
- โครงสร้าง
- Workshop: ระบบแจ้งเตือน Email และ SMS
- ลำดับการทำงาน
- ข้อดีและข้อจำกัด
- Factory Method vs Simple Factory vs Abstract Factory
- ควรใช้เมื่อใด
- แบบฝึกหัดต่อยอด
- สรุป
#Factory Method คืออะไร
Factory Method เป็น Creational Design Pattern ที่กำหนดเมธอดสำหรับสร้างออบเจ็กต์ไว้ในคลาสแม่ (Creator) แต่เปิดโอกาสให้คลาสลูก (Concrete Creator) ตัดสินใจว่าจะสร้างออบเจ็กต์ชนิดใด โดยโค้ดที่เรียกใช้งานพึ่งพา interface ของผลิตภัณฑ์ (Product) แทนคลาสจริง
จุดสำคัญ: Factory Method ใช้ inheritance และ polymorphism เพื่อเปลี่ยนชนิดของออบเจ็กต์ที่สร้าง ต่างจาก Simple Factory ซึ่งมักใช้เมธอดเดียวพร้อม
switchเลือกชนิด
#โครงสร้าง
classDiagram
class Notification {
<<interface>>
+send(String message) void
}
class EmailNotification {
+send(String message) void
}
class SmsNotification {
+send(String message) void
}
class NotificationCreator {
<<abstract>>
+notifyUser(String message) void
#createNotification() Notification
}
class EmailNotificationCreator {
#createNotification() Notification
}
class SmsNotificationCreator {
#createNotification() Notification
}
Notification <|.. EmailNotification
Notification <|.. SmsNotification
NotificationCreator <|-- EmailNotificationCreator
NotificationCreator <|-- SmsNotificationCreator
NotificationCreator ..> Notification : creates / uses
#Workshop: ระบบแจ้งเตือน Email และ SMS
ตัวอย่างนี้ใช้ Java 17+ และแยกคลาสเป็นไฟล์เพื่อให้เห็นความรับผิดชอบชัดเจน
#1. Product interface
Notification.java
public interface Notification {
void send(String message);
}
#2. Concrete Products
EmailNotification.java
public class EmailNotification implements Notification {
@Override
public void send(String message) {
System.out.println("EMAIL: " + message);
}
}
SmsNotification.java
public class SmsNotification implements Notification {
@Override
public void send(String message) {
System.out.println("SMS: " + message);
}
}
#3. Abstract Creator
NotificationCreator.java
public abstract class NotificationCreator {
// Factory Method: subclasses decide the concrete product.
protected abstract Notification createNotification();
public void notifyUser(String message) {
Notification notification = createNotification();
notification.send(message);
}
}
#4. Concrete Creators
EmailNotificationCreator.java
public class EmailNotificationCreator extends NotificationCreator {
@Override
protected Notification createNotification() {
return new EmailNotification();
}
}
SmsNotificationCreator.java
public class SmsNotificationCreator extends NotificationCreator {
@Override
protected Notification createNotification() {
return new SmsNotification();
}
}
#5. Client
Main.java
public class Main {
public static void main(String[] args) {
NotificationCreator creator = new EmailNotificationCreator();
creator.notifyUser("Your order has shipped");
creator = new SmsNotificationCreator();
creator.notifyUser("Your OTP is 123456");
}
}
#6. รันโปรแกรม
วางไฟล์ .java ทั้งหมดไว้ในไดเรกทอรีเดียวกัน แล้วรัน
javac *.java
java Main
ผลลัพธ์
EMAIL: Your order has shipped
SMS: Your OTP is 123456
#ลำดับการทำงาน
sequenceDiagram
participant Client
participant Creator as EmailNotificationCreator
participant Product as EmailNotification
Client->>Creator: notifyUser("Hello")
Creator->>Creator: createNotification()
Creator->>Product: new EmailNotification()
Creator->>Product: send("Hello")
Product-->>Client: Output: EMAIL: Hello
#ข้อดีและข้อจำกัด
| ข้อดี | ข้อจำกัด |
|---|---|
| ลดการผูกติดกับคลาสผลิตภัณฑ์จริง | จำนวนคลาสเพิ่มขึ้น |
| เพิ่มชนิดผลิตภัณฑ์ได้โดยสร้าง Concrete Creator ใหม่ | อาจซับซ้อนเกินไปสำหรับระบบขนาดเล็ก |
| สนับสนุน Open/Closed Principle | การเลือก Creator ที่ runtime ยังต้องมีองค์ประกอบจัดการ |
| รวมขั้นตอนการใช้งานผลิตภัณฑ์ไว้ใน Creator | ไม่ได้กำจัด new ออกจากระบบทั้งหมด |
#Factory Method vs Simple Factory vs Abstract Factory
| Pattern | แนวคิดหลัก |
|---|---|
| Simple Factory | เมธอด/คลาสกลางเลือกสร้างผลิตภัณฑ์ตามพารามิเตอร์ (ไม่ใช่หนึ่งใน GoF 23 patterns) |
| Factory Method | ให้ subclass override เมธอดเพื่อเลือกผลิตภัณฑ์หนึ่งประเภท |
| Abstract Factory | interface สำหรับสร้างชุดผลิตภัณฑ์ที่สัมพันธ์กัน โดยไม่ระบุคลาสจริง |
#ควรใช้เมื่อใด
เหมาะเมื่อโค้ดส่วนกลางต้องทำงานกับผลิตภัณฑ์ผ่าน interface เดียวกัน แต่ต้องเปิดให้ subclass กำหนดชนิดผลิตภัณฑ์ เช่น ตัวส่งข้อความ ตัวอ่านไฟล์ หรือไดรเวอร์จัดเก็บข้อมูล หากเพียงเลือกชนิดด้วยเงื่อนไขไม่กี่กรณีและไม่มีความจำเป็นต้องขยายด้วย subclass การใช้ Simple Factory หรือ dependency injection อาจตรงไปตรงมากว่า
#แบบฝึกหัดต่อยอด
- เพิ่ม
PushNotificationและPushNotificationCreatorโดยไม่แก้ไขNotificationCreator. - เขียน JUnit 5 test เพื่อทดสอบว่า Creator แต่ละชนิดส่งข้อความได้ถูกต้อง โดยใช้ test double แทนการพิมพ์ลง console.
- เปลี่ยนตัวอย่างให้ส่ง
NotificationResultและจัดการข้อผิดพลาดจากผู้ให้บริการภายนอก.
#สรุป
Factory Method แยก การสร้างออบเจ็กต์ ออกจาก กระบวนการใช้งานออบเจ็กต์ ผ่าน abstract Creator และ Concrete Creator ทำให้เพิ่มผลิตภัณฑ์ชนิดใหม่ได้โดยลดผลกระทบต่อโค้ดหลัก แต่ควรเลือกใช้ให้เหมาะกับความซับซ้อนของระบบ