Factory — รูปแบบการสร้างที่มอบหมายการสร้างออบเจ็กต์ให้กับเมธอดของโรงงาน ในการพัฒนาโมบายล์ Factory Method และ Abstract Factory ถูกใช้เพื่อสร้าง ViewModel, NetworkClient, Repository และการพึ่งพาอื่น ๆ Factory แยกลอจิกการสร้างอินสแตนซ์ ทำให้การเปลี่ยนการ implementations ง่ายขึ้น รายละเอียดเพิ่มเติม — ที่ Refactoring Guru: Factory Method
ประเด็นสำคัญ
Factory — รูปแบบการออกแบบการสร้างจากแคตตาล็อก GoF แนวคิดหลัก: ย้ายลอจิกการสร้างออบเจ็กต์ออกจากโค้ดไคลเอนต์ไปยังเมธอดหรือคลาสที่แยกต่างหาก ไคลเอนต์ทำงานกับอินเทอร์เฟซหรือคลาสนามธรรม ในขณะที่ implementation ที่เป็นรูปธรรมถูกสร้างโดยโรงงาน สิ่งนี้ใช้หลักการการกลับด้านการพึ่งพา: ไคลเอนต์ไม่พึ่งพาคลาสที่เป็นรูปธรรม แต่พึ่งพาเฉพาะสิ่งที่เป็นนามธรรม
สองรูปแบบ ของ Factory: Factory Method และ Abstract Factory Factory Method — เมธอดเดียวในคลาสที่คลาสย่อยโอเวอร์ไรด์เพื่อสร้างออบเจ็กต์ Abstract Factory — อินเทอร์เฟซที่มีตระกูลของเมธอดโรงงานสำหรับสร้างกลุ่มของออบเจ็กต์ที่เกี่ยวข้องกัน ทั้งสองรูปแบบแก้ปัญหาเดียวกัน: ไคลเอนต์ไม่เรียก new MyClass() โดยตรง แต่ขอให้โรงงานสร้างออบเจ็กต์ตามประเภทหรือพารามิเตอร์ของมัน
Factory vs new() — การสร้างออบเจ็กต์โดยตรงเชื่อมโยงโค้ดกับ implementation ที่เป็นรูปธรรมอย่างแน่นหนา Factory เพิ่มชั้น: การเปลี่ยน implementation ต้องการการแก้ไขเฉพาะในโรงงานเท่านั้น ไม่ใช่ไคลเอนต์ทั้งหมด ในการพัฒนาโมบายล์ Factory ถูกใช้อย่างแข็งขันในการสร้าง ViewModel (ViewModelProvider.Factory), ไคลเอนต์เครือข่าย (Retrofit.create()), อะแดปเตอร์รายการ และโรงงานซีเรียลไลเซชัน คอนเทนเนอร์ DI (Dagger, Koin) สร้างโรงงานโดยอัตโนมัติ
Factory Method — เมธอดที่ประกาศในโปรโตคอลหรือคลาสนามธรรม ซึ่งส่งคืนออบเจ็กต์ของประเภทเฉพาะ คลาสย่อย implement เมธอด สร้างอินสแตนซ์ที่เป็นรูปธรรม ใน Swift อาจเป็นเมธอดแบบสแตติกในโปรโตคอลหรือเมธอดในคลาสพื้นฐาน ใน Kotlin — companion object ที่มีเมธอดโรงงานหรือ open fun ในคลาสนามธรรม รูปแบบนี้ถูกใช้อย่างกว้างขวางในการสร้างพาร์เซอร์ โรงงานข้อผิดพลาด และตัวสร้างคำสั่งค้นหา
protocol PaymentGateway {
func processPayment(amount: Decimal) async throws -> PaymentResult
}
final class StripeGateway: PaymentGateway { /* ... */ }
final class ApplePayGateway: PaymentGateway { /* ... */ }
enum PaymentType { case stripe, applePay }
final class PaymentFactory {
// Factory Method
static func create(type: PaymentType) -> PaymentGateway {
switch type {
case .stripe: return StripeGateway()
case .applePay: return ApplePayGateway()
}
}
}
// การใช้งาน
let gateway = PaymentFactory.create(type: .stripe)
เวอร์ชัน Kotlin ของ Factory Method ใช้ companion object หรือ sealed class เพื่อจำกัดประเภท Sealed class รับประกันว่าเมื่อสาขา when ครอบคลุมทุกประเภทที่เป็นไปได้ — คอมไพเลอร์ตรวจสอบความสมบูรณ์ ซึ่งเป็นเรื่องปกติสำหรับโปรเจกต์ Android ที่โรงงานสร้าง implementations Repository หรือ DataSource ที่แตกต่างกันตาม build flavour หรือการกำหนดค่า
sealed class PaymentType {
object Stripe : PaymentType()
object ApplePay : PaymentType()
}
interface PaymentGateway {
suspend fun processPayment(amount: BigDecimal): PaymentResult
}
class PaymentFactory {
companion object {
fun create(type: PaymentType): PaymentGateway = when (type) {
PaymentType.Stripe -> StripeGateway()
PaymentType.ApplePay -> ApplePayGateway()
}
}
}
Abstract Factory — รูปแบบสำหรับสร้างตระกูลของออบเจ็กต์ที่เกี่ยวข้องกันหรือพึ่งพากันโดยไม่ระบุคลาสที่เป็นรูปธรรมของพวกมัน ไคลเอนต์ทำงานกับอินเทอร์เฟซของโรงงานนามธรรม ซึ่งกำหนดเมธอดสำหรับสร้างแต่ละผลิตภัณฑ์ของตระกูล โรงงานที่เป็นรูปธรรม implement อินเทอร์เฟซและสร้างออบเจ็กต์ของรูปแบบเฉพาะ ตัวอย่างเช่น โรงงานส่วนประกอบ UI สำหรับ iOS สร้าง UIButton, UILabel, UITableView ในขณะที่สำหรับ Android — Button, TextView, RecyclerView
Abstract Factory vs Factory Method — Factory Method สร้างออบเจ็กต์หนึ่งประเภทผ่านการสืบทอด Abstract Factory สร้างตระกูลของออบเจ็กต์ผ่านองค์ประกอบ Factory Method ถูกโอเวอร์ไรด์ในคลาสย่อย Abstract Factory จัดหาเมธอดโรงงานหลายตัวผ่านโปรโตคอล Abstract Factory มักประกอบด้วย Factory Method หลายตัว ในการพัฒนาโมบายล์ Abstract Factory ถูกใช้สำหรับส่วนประกอบที่ขึ้นกับแพลตฟอร์ม การออกแบบธีม และโรงงานฐานข้อมูล
| ลักษณะ | Factory Method | Abstract Factory |
|---|---|---|
| จำนวนผลิตภัณฑ์ | หนึ่ง | ตระกูล (หลายตัว) |
| กลไก | การสืบทอด (override) | องค์ประกอบ (โปรโตคอล/อินเทอร์เฟซ) |
| ตัวอย่าง iOS | PaymentFactory.create() | UIComponentFactory สำหรับ iOS/Android |
| ตัวอย่าง Android | ViewModelProvider.Factory | ThemeFactory: การสร้างปุ่ม ข้อความ การ์ด |
| ความยืดหยุ่น | การเปลี่ยนคลาสย่อยอย่างง่าย | การเปลี่ยนตระกูลทั้งหมด |
กรณีจริง ของ Abstract Factory ใน Android — การ implementation ฐานข้อมูลประเภทต่าง ๆ (SQLite vs Room) ผ่านอินเทอร์เฟซ DatabaseFactory เดียว โรงงานสร้างออบเจ็กต์ DAO การโยกย้าย และพูลการเชื่อมต่อ ใน iOS — โรงงานบริการสำหรับสภาพแวดล้อมต่าง ๆ (Development/Staging/Production) Abstract Factory ไม่ค่อยถูกใช้โดยตรง — หน้าที่ของมันถูกทำโดยคอนเทนเนอร์ DI (Dagger Module, Swinject Assembly)
Swift Factory ถูก implement ผ่านโปรโตคอลและเมธอดแบบสแตติก โปรโตคอล Factory ประกาศเมธอด create() ที่ส่งคืนประเภทนามธรรม โรงงานที่เป็นรูปธรรม implement โปรโตคอลและสร้างออบเจ็กต์ที่ต้องการ Swift ไม่ต้องการคลาสโรงงานแยกต่างหากสำหรับกรณีง่าย — เมธอดแบบสแตติกใน enum หรือ struct ก็เพียงพอ สำหรับสถานการณ์ที่ซับซ้อน ใช้โปรโตคอล Factory ที่มีการฉีด DI
Factory ใน iOS SDK — โรงงานของระบบมากมาย: UIStoryboard.instantiateViewController(withIdentifier:), NSKeyedUnarchiver.unarchivedObject(ofClass:from:), JSONDecoder().decode(_:from:) นักพัฒนาสร้างโรงงานสำหรับ ViewController (StoryboardFactory) สำหรับบริการ (ServiceFactory) และสำหรับโมเดลข้อมูล Factory Method ถูกใช้อย่างแข็งขันในสถาปัตยกรรม VIPER และ Clean Swift สำหรับสร้างโมดูลหน้าจอ
Factory + DI — ทางเลือกที่ทันสมัย: คอนเทนเนอร์ DI (Swinject, Factory) สร้างโรงงานสำหรับประเภทที่ลงทะเบียนโดยอัตโนมัติ คอนเทนเนอร์เก็บสูตรการสร้างออบเจ็กต์และแก้ไขการพึ่งพา ไลบรารี Factory (github.com/hmlongco/Factory) ใช้ @Injected(.service) สำหรับการฉีดอัตโนมัติ โรงงาน DI ถูกทดสอบโดยการแทนที่โมดูลทั้งหมดด้วยบรรทัดเดียว: container.register { MockService() }
Android Factory — ตัวอย่างคลาสสิก: ViewModelProvider.Factory สำหรับสร้าง ViewModel ด้วยพารามิเตอร์ Google แนะนำให้ใช้ Hilt สำหรับการสร้างโรงงาน ViewModel อัตโนมัติ — คำอธิบายประกอบ @HiltViewModel สร้าง Factory โดยอัตโนมัติ สำหรับออบเจ็กต์ง่าย ๆ ใช้ companion object ที่มีเมธอด create() หรือ invoke() ใน Kotlin ตัวดำเนินการ invoke อนุญาตให้เรียกโรงงานเหมือนฟังก์ชัน: Factory(param)
Factory ใน Jetpack Compose — โรงงานถูกใช้สำหรับสร้างสเตทและเอฟเฟกต์ remember { Factory.create() } สร้างออบเจ็กต์ในการเรนเดอร์ครั้งแรกและเก็บไว้ตลอดอายุของ composable ViewModel ใน Compose ถูกสร้างผ่าน viewModel() — นี่คือโรงงานที่จัดการโดย Hilt ใน Compose โรงงานพบได้น้อยกว่าอย่างชัดเจน เนื่องจาก DI และ Compose StateManager จัดการการสร้างออบเจ็กต์
Factory vs Hilt — Dagger/Hilt สร้างโรงงานโดยอัตโนมัติในเวลาคอมไพล์ @Module + @Providers แทนที่ Factory Method, @Binds แทนที่ Abstract Factory โรงงานแบบ manual ยังคงมีความเกี่ยวข้องสำหรับการเลือก implementation แบบไดนามิกในรันไทม์ (การทดสอบ A/B, ฟีเจอร์แฟล็ก) สำหรับการพึ่งพาแบบสแตติก Hilt ทำให้การสร้างออบเจ็กต์เป็นอัตโนมัติอย่างสมบูรณ์ — นักพัฒนาเขียนเฉพาะอินเทอร์เฟซและคำอธิบายประกอบ
คำถามที่พบบ่อย
Factory Method สร้างออบเจ็กต์หนึ่งประเภทผ่านการสืบทอด — คลาสย่อยโอเวอร์ไรด์เมธอดโรงงาน Abstract Factory สร้างตระกูลของออบเจ็กต์ผ่านองค์ประกอบ — อินเทอร์เฟซโรงงานประกาศเมธอดสำหรับหลายผลิตภัณฑ์ Factory Method ง่ายกว่า Abstract Factory ยืดหยุ่นกว่าสำหรับส่วนประกอบที่ขึ้นกับแพลตฟอร์มหรือตามธีม
Factory เหมาะสมสำหรับการเลือก implementation แบบไดนามิกในรันไทม์ (การทดสอบ A/B, ฟีเจอร์แฟล็ก, API ที่แตกต่างสำหรับระดับที่แตกต่างกัน) DI (Hilt, Dagger, Koin) เหมาะกว่าสำหรับการพึ่งพาแบบสแตติก — ทำให้การสร้างและการฉีดเป็นอัตโนมัติ Factory และ DI ไม่แยกกัน: DI สามารถใช้ Factory ภายในโมดูล
Factory ถูกทดสอบโดยการแทนที่โรงงานผ่านโปรโตคอล ในการทดสอบ จะสร้าง TestFactory ที่ implement โปรโตคอลเดียวกันและส่งคืนออบเจ็กต์จำลอง สำหรับเมธอด Factory แบบสแตติก การทดสอบซับซ้อนกว่า — ต้องใช้คอนเทนเนอร์ DI หรือ swizzling แนะนำให้ใช้โปรโตคอลสำหรับ Factory เสมอเพื่อรักษาความสามารถในการทดสอบ
ViewModelProvider.Factory คืออินเทอร์เฟซจาก Jetpack ที่อนุญาตให้สร้าง ViewModel ด้วยพารามิเตอร์ที่กำหนดเอง หากไม่มีโรงงาน ViewModel จะถูกสร้างผ่านรีเฟลกชันและสามารถมีคอนสตรัคเตอร์ว่างเท่านั้น Factory รับพารามิเตอร์ (รีพอสิทอรี, บริบทแอปพลิเคชัน) และส่งต่อไปยังคอนสตรัคเตอร์ ViewModel Hilt สร้าง Factory โดยอัตโนมัติสำหรับ @HiltViewModel
Factory implement หลักการเปิด/ปิด: ระบบเปิดสำหรับการขยาย (implementation ใหม่ถูกเพิ่มเข้าไปในโรงงาน) แต่ปิดสำหรับการแก้ไข (โค้ดไคลเอนต์ไม่เปลี่ยนแปลง) การเพิ่มประเภทผลิตภัณฑ์ใหม่ต้องการการแก้ไขเฉพาะในโรงงาน ไม่ใช่ไคลเอนต์ทั้งหมด นี่คือข้อได้เปรียบหลักของ Factory เหนือการสร้างออบเจ็กต์โดยตรง
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม