メインコンテンツへ移動

เนื้อหาภาษาไทย / タイ語のコンテンツ

システムガイド 内容確認済み

Factory Pattern: สร้าง Object โดยไม่ต้องระบุ Class

บทความนี้แนะนำ Factory Pattern ซึ่งเป็น Design Pattern ที่ช่วยให้เราสร้าง Object โดยไม่ต้องระบุ Class ที่ต้องการสร้างโดยตรง โดยมี "โรงงาน" ที่ทำหน้าที่สร้าง Obj...

Factory Pattern: สร้าง Object โดยไม่ต้องระบุ Class

ในบทที่แล้ว เราได้เรียนรู้เกี่ยวกับ Singleton Pattern ซึ่งเป็นการสร้าง Object เพียงตัวเดียวในระบบ แต่ในบางครั้ง เราต้องการสร้าง Object หลายตัว แต่ไม่อยากให้โค้ดส่วนอื่น ๆ ต้องรู้ว่าเรากำลังสร้าง Object จาก Class อะไร นี่คือที่มาของ Factory Pattern

Factory Pattern คืออะไร?

Factory Pattern เป็น Design Pattern ที่ช่วยให้เราสร้าง Object ได้โดยไม่ต้องระบุ Class ที่ต้องการสร้างโดยตรง กล่าวคือ เรามี "โรงงาน" (Factory) ที่ทำหน้าที่สร้าง Object ให้เรา โดยผู้ใช้งาน (Client) เพียงแค่บอกว่าต้องการ Object แบบไหน โรงงานก็จะสร้าง Object ที่เหมาะสมให้

ลองนึกภาพโรงงานผลิตรถยนต์ ผู้บริโภค (Client) ต้องการรถยนต์ (Object) แต่ไม่ได้สนใจว่ารถยนต์คันนั้นถูกผลิตจากเครื่องจักร (Class) อะไรบ้าง ผู้บริโภคเพียงแค่บอกว่าต้องการรถยนต์ประเภทไหน (เช่น รถเก๋ง รถกระบะ) โรงงานก็จะผลิตรถยนต์ประเภทนั้นให้

ทำไมต้องใช้ Factory Pattern?

  • ลดความซับซ้อนของโค้ด: Client ไม่จำเป็นต้องรู้ว่า Class ไหนที่ใช้สร้าง Object ทำให้โค้ดอ่านง่ายและบำรุงรักษาง่ายขึ้น
  • เพิ่มความยืดหยุ่น: เราสามารถเปลี่ยนแปลง Class ที่ใช้สร้าง Object ได้โดยไม่ต้องแก้ไขโค้ดของ Client
  • ซ่อนรายละเอียดการสร้าง Object: Client ไม่จำเป็นต้องรู้รายละเอียดการสร้าง Object ที่ซับซ้อน
  • แยกส่วนการสร้าง Object ออกจากส่วนใช้งาน: ทำให้โค้ดมีความรับผิดชอบที่ชัดเจน (Single Responsibility Principle)

การ Implement Factory Pattern

โดยทั่วไป Factory Pattern ประกอบด้วยส่วนประกอบหลักดังนี้:

  • Product: Interface หรือ Abstract Class ที่กำหนด Interface สำหรับ Object ที่ Factory จะสร้าง
  • Concrete Product: Class ที่ Implement Product Interface
  • Factory: Class ที่มี Method สำหรับสร้าง Object โดย Method นี้จะ return Product Interface
  • Client: โค้ดที่ใช้งาน Factory เพื่อสร้าง Object

ตัวอย่าง: สมมติว่าเราต้องการสร้างระบบจัดการรูปภาพที่รองรับรูปภาพหลายรูปแบบ (เช่น JPEG, PNG, GIF) เราสามารถใช้ Factory Pattern เพื่อสร้าง Object ของแต่ละรูปแบบรูปภาพได้

<?php

// Product Interface
interface Image {
    public function load(string $filename): void;
    public function save(string $filename): void;
}

// Concrete Product (JPEG)
class JpegImage implements Image {
    public function load(string $filename): void {
        echo "Loading JPEG image from: " . $filename . "<br>";
    }

    public function save(string $filename): void {
        echo "Saving JPEG image to: " . $filename . "<br>";
    }
}

// Concrete Product (PNG)
class PngImage implements Image {
    public function load(string $filename): void {
        echo "Loading PNG image from: " . $filename . "<br>";
    }

    public function save(string $filename): void {
        echo "Saving PNG image to: " . $filename . "<br>";
    }
}

// Factory
class ImageFactory {
    public static function createImage(string $type): Image {
        switch ($type) {
            case 'jpeg':
                return new JpegImage();
            case 'png':
                return new PngImage();
            default:
                throw new Exception("Unsupported image type: " . $type);
        }
    }
}

// Client
try {
    $jpegImage = ImageFactory::createImage('jpeg');
    $jpegImage->load('image.jpeg');
    $jpegImage->save('new_image.jpeg');

    $pngImage = ImageFactory::createImage('png');
    $pngImage->load('image.png');
    $pngImage->save('new_image.png');

    // Uncomment to test the exception
    // $gifImage = ImageFactory::createImage('gif');
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "<br>";
}

?>

คำอธิบายโค้ด:

  • Image เป็น Interface ที่กำหนด Method load และ save สำหรับ Object ที่แสดงถึงรูปภาพ
  • JpegImage และ PngImage เป็น Concrete Class ที่ Implement Image Interface และ Implement Method load และ save ให้ทำงานกับรูปภาพ JPEG และ PNG ตามลำดับ
  • ImageFactory เป็น Factory Class ที่มี Static Method createImage ซึ่งรับ Parameter เป็น String $type ที่ระบุประเภทของรูปภาพที่ต้องการสร้าง Method นี้จะสร้าง Object ของ Class ที่เหมาะสม (JpegImage หรือ PngImage) และ Return Image Interface
  • Client Code ใช้ ImageFactory::createImage() เพื่อสร้าง Object โดยไม่ต้องรู้ว่า Object นั้นถูกสร้างจาก Class อะไร

ข้อดีและข้อเสียของ Factory Pattern

ข้อดี:

  • ลดการ Coupling: Client ไม่ขึ้นอยู่กับ Concrete Class ที่ใช้สร้าง Object
  • เพิ่มความยืดหยุ่น: สามารถเปลี่ยนแปลง Concrete Class ที่ใช้สร้าง Object ได้ง่าย
  • ซ่อนรายละเอียดการสร้าง Object: Client ไม่จำเป็นต้องรู้ขั้นตอนการสร้าง Object ที่ซับซ้อน
  • ง่ายต่อการทดสอบ: สามารถ Mock Factory เพื่อทดสอบ Client Code ได้ง่ายขึ้น

ข้อเสีย:

  • เพิ่มความซับซ้อน: อาจทำให้โค้ดซับซ้อนขึ้นเล็กน้อยเมื่อเทียบกับการสร้าง Object โดยตรง
  • ต้องมีการวางแผน: ต้องวางแผนล่วงหน้าว่า Object ประเภทใดบ้างที่ Factory จะต้องสร้าง
  • Class Factory อาจมีขนาดใหญ่: หากมี Object หลายประเภทที่ Factory ต้องสร้าง Class Factory อาจมีขนาดใหญ่และซับซ้อน

ทางเลือกอื่นนอกเหนือจาก Factory Pattern

แม้ว่า Factory Pattern จะมีประโยชน์หลายอย่าง แต่ก็ไม่ใช่ทางออกที่ดีที่สุดเสมอไป ในบางกรณี Dependency Injection (DI) อาจเป็นทางเลือกที่ดีกว่า DI ช่วยให้เรา Inject Dependencies (Object ที่ Class ต้องการ) เข้ามาใน Class โดยไม่ต้องให้ Class สร้าง Object เอง ซึ่งจะช่วยลดการ Coupling และเพิ่มความยืดหยุ่นของโค้ด

สรุป

Factory Pattern เป็น Design Pattern ที่มีประโยชน์ในการสร้าง Object โดยไม่ต้องระบุ Class ที่ต้องการสร้างโดยตรง ซึ่งช่วยลดความซับซ้อนของโค้ด เพิ่มความยืดหยุ่น และซ่อนรายละเอียดการสร้าง Object อย่างไรก็ตาม ควรพิจารณาข้อดีข้อเสียของ Factory Pattern และเปรียบเทียบกับทางเลือกอื่น ๆ เช่น Dependency Injection เพื่อเลือกใช้ Design Pattern ที่เหมาะสมกับสถานการณ์

ในบทถัดไป เราจะพูดถึง Strategy Pattern ซึ่งเป็น Design Pattern ที่ช่วยให้เราเลือก Algorithm ใน Runtime

Office.in.th Custom Service

この構成をもとにシステムを開発・カスタマイズしたいですか?

Office.in.th は、エンタープライズ Web アプリケーション、API 連携、官民の業務管理システムの設計・開発を承り、長期的なサポートも提供します。

ソフトウェア開発サービスを見る