0Pricing
PHP Academy · บทเรียน

รูปแบบการสร้าง: Factory, Builder, Singleton

ควบคุมการสร้างออบเจ็กต์อย่างเป็นระเบียบด้วยรูปแบบการสร้าง

รูปแบบการสร้าง: Factory, Builder, Singleton เป็นบทเรียน PHP Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน PHP Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน

ควบคุมการสร้าง

รูปแบบการสร้างแยก สิ่งที่คุณต้องการ ออกจาก วิธีสร้างสิ่งนั้น เมื่อการสร้างมีเงื่อนไข หลายขั้นตอน หรือต้องรวมศูนย์ การกระจาย new ไปทั่วโค้ดเบสจะทำให้ผู้เรียกผูกติดกับคลาสรูปธรรม ที่นี่เราจะครอบคลุมโรงงาน (รวมถึงเมธอดโรงงาน) ตัวสร้างสำหรับการประกอบที่ซับซ้อน และซิงเกิลตัน (พร้อมข้อควรระวัง)

โรงงานอย่างง่าย

โรงงานอย่างง่าย รวมศูนย์การตัดสินใจสร้างไว้เบื้องหลังเมธอดเดียว ผู้เรียกขอประเภทเชิงตรรกะและได้รับอินสแตนซ์รูปธรรมที่กำหนดค่าแล้ว โดยไม่จำเป็นต้องรู้ชื่อคลาส

<?php
interface Notifier { public function send(string $msg): string; }
final class EmailNotifier implements Notifier {
    public function send(string $m): string { return "email: $m"; }
}
final class SmsNotifier implements Notifier {
    public function send(string $m): string { return "sms: $m"; }
}

final class NotifierFactory {
    public static function make(string $channel): Notifier {
        return match ($channel) {
            'email' => new EmailNotifier(),
            'sms'   => new SmsNotifier(),
            default => throw new InvalidArgumentException($channel),
        };
    }
}
echo NotifierFactory::make('sms')->send('Hi'), PHP_EOL;

เมธอดโรงงาน

รูปแบบเมธอดโรงงานเลื่อนการสร้างอินสแตนซ์ไปยังคลาสย่อย คลาสฐานกำหนดอัลกอริทึมที่เรียกใช้เมธอดนามธรรม create() ส่วนคลาสย่อยแต่ละคลาสจะตัดสินใจเลือกผลิตภัณฑ์รูปธรรม วิธีนี้เป็นมิตรต่อ OCP เพราะคุณเพิ่มผู้สร้างรายใหม่ได้โดยไม่ต้องแก้ไขผู้สร้างที่มีอยู่

<?php
abstract class ReportExporter {
    abstract protected function create(): string;
    public function export(): string {
        return 'Exported as ' . $this->create();
    }
}
final class PdfExporter extends ReportExporter {
    protected function create(): string { return 'PDF'; }
}
final class CsvExporter extends ReportExporter {
    protected function create(): string { return 'CSV'; }
}
echo (new PdfExporter())->export(), PHP_EOL;
echo (new CsvExporter())->export(), PHP_EOL;

โรงงานนามธรรม

โรงงานนามธรรมสร้างตระกูลอ็อบเจกต์ที่เกี่ยวข้องกัน ซึ่งต้องใช้ร่วมกัน (เช่น MySqlConnection + MySqlQueryBuilder) วิธีนี้รับประกันว่าส่วนประกอบต่าง ๆ เข้ากันได้ เพราะโรงงานหนึ่งแห่งให้ชุดทั้งหมด ใช้รูปแบบนี้เมื่อตระกูลผลิตภัณฑ์ต้องคงความสอดคล้องกันภายใน

ตัวสร้าง: ปัญหา

เมื่ออ็อบเจกต์ต้องรับพารามิเตอร์เสริมจำนวนมาก ตัวสร้างจะกลายเป็นรายการอาร์กิวเมนต์ตามตำแหน่งที่อ่านยาก หรือเป็นเมธอดโอเวอร์โหลดที่เพิ่มพารามิเตอร์ต่อเนื่อง ซึ่ง PHP ก็ไม่มีให้ใช้ด้วยซ้ำ รูปแบบตัวสร้างจะประกอบอ็อบเจกต์ที่ซับซ้อนทีละขั้นตอน และส่งคืนผลิตภัณฑ์ที่สร้างเสร็จและถูกต้องในตอนท้าย

ตัวสร้างแบบต่อเนื่อง

ตัวสร้างแบบต่อเนื่องจะส่งคืน $this จากเมธอดกำหนดค่าแต่ละเมธอด จากนั้น build() จะสร้างผลลัพธ์ที่เปลี่ยนแปลงไม่ได้ วิธีนี้ทำให้ตัวผลิตภัณฑ์เรียบง่าย และย้ายตรรกะการประกอบไปไว้ในตัวสร้าง

<?php
final class Query {
    public function __construct(public readonly string $sql) {}
}
final class QueryBuilder {
    private string $table = '';
    private array $where = [];
    public function from(string $t): self { $this->table = $t; return $this; }
    public function where(string $c): self { $this->where[] = $c; return $this; }
    public function build(): Query {
        $sql = "SELECT * FROM {$this->table}";
        if ($this->where) { $sql .= ' WHERE ' . implode(' AND ', $this->where); }
        return new Query($sql);
    }
}
echo (new QueryBuilder())->from('users')->where('age > 18')->build()->sql, PHP_EOL;

ตัวสร้างกับตัวสร้างที่ตั้งชื่อ

สำหรับกรณีที่ง่ายกว่า อาร์กิวเมนต์แบบตั้งชื่อของ PHP 8 และตัวสร้างที่ตั้งชื่อ (เมธอดโรงงานแบบสแตติก) มักเหมาะกว่าการใช้ตัวสร้างเต็มรูปแบบ

  • ใช้อาร์กิวเมนต์แบบตั้งชื่อเมื่อข้อมูลทั้งหมดพร้อมในครั้งเดียว
  • ใช้ตัวสร้างเมื่อการประกอบมีหลายขั้นตอน มีเงื่อนไข หรือนำกลับมาใช้ซ้ำในหลายจุดที่เรียกใช้งาน
<?php
final class Money {
    private function __construct(public readonly int $cents, public readonly string $cur) {}
    public static function fromDollars(float $d): self {
        return new self((int) round($d * 100), 'USD');
    }
    public static function zero(string $cur = 'USD'): self {
        return new self(0, $cur);
    }
}
var_dump(Money::fromDollars(19.99)->cents); // int(1999)

ซิงเกิลตัน

ซิงเกิลตันรับประกันว่าจะมีอินสแตนซ์เดียวพร้อมจุดเข้าถึงส่วนกลาง ใช้ตัวสร้างส่วนตัวและตัวเข้าถึงแบบสแตติกเพื่อสร้างรูปแบบนี้ รูปแบบนี้มีประโยชน์อย่างแท้จริงกับสิ่งที่ต้องมีเพียงหนึ่งเดียวภายในกระบวนการ แต่ก็เป็นรูปแบบที่ถูกใช้ในทางที่ผิดมากที่สุดเช่นกัน

<?php
final class Config {
    private static ?self $instance = null;
    private array $data = ['debug' => true];
    private function __construct() {}
    public static function instance(): self {
        return self::$instance ??= new self();
    }
    public function get(string $k): mixed { return $this->data[$k] ?? null; }
}
var_dump(Config::instance()->get('debug'));
var_dump(Config::instance() === Config::instance()); // true

เหตุใดซิงเกิลตันจึงสร้างปัญหา

ซิงเกิลตันทำให้เกิดสถานะส่วนกลางที่ซ่อนอยู่ ผู้เรียกเข้าถึง Config::instance() แทนการประกาศการพึ่งพา ส่งผลให้ทดสอบและทำงานแบบขนานได้ยาก ใน PHP สมัยใหม่ ควรลงทะเบียนอินสแตนซ์ร่วมเพียงหนึ่งเดียวไว้ในคอนเทนเนอร์ DI (วงจรชีวิตแบบ "อินสแตนซ์เดียว") แล้วฉีดอินสแตนซ์นั้นเข้าไป คุณจะได้อินสแตนซ์เดียวโดยไม่ต้องผูกติดกับสถานะส่วนกลาง

การเลือกเครื่องมือที่เหมาะสม

  • อย่างง่าย/เมธอดโรงงาน: ซ่อนคลาสรูปธรรมไว้เบื้องหลังการตัดสินใจสร้าง
  • โรงงานนามธรรม: สร้างตระกูลผลิตภัณฑ์ที่เข้ากันได้
  • ตัวสร้าง: ประกอบอ็อบเจกต์ที่ซับซ้อนทีละขั้นตอน
  • ซิงเกิลตัน: ทางเลือกสุดท้าย ควรเลือกบริการร่วมที่จัดการโดยคอนเทนเนอร์

ทั้งสี่รูปแบบช่วยลดการผูกติดกับตัวสร้างรูปธรรม ทำให้โค้ดขยายและทดสอบได้ง่ายขึ้น

โรงงานที่ใช้รีจิสทรี

โรงงานแบบไดนามิกจะค้นหาผู้สร้างในรีจิสทรี ทำให้ประเภทใหม่ลงทะเบียนตัวเองได้โดยไม่ต้องแก้ไขโรงงาน (เป็นไปตาม OCP อย่างแท้จริง) ระบบปลั๊กอินและตัวทำอนุกรมใช้แนวทางนี้เพื่อแปลงชื่อประเภทเป็นตัวสร้างขณะทำงาน

<?php
interface Shape { public function name(): string; }
final class Circle implements Shape { public function name(): string { return 'circle'; } }
final class Square implements Shape { public function name(): string { return 'square'; } }

final class ShapeRegistry {
    private array $creators = [];
    public function register(string $key, callable $factory): void {
        $this->creators[$key] = $factory;
    }
    public function create(string $key): Shape {
        return ($this->creators[$key] ?? throw new InvalidArgumentException($key))();
    }
}
$r = new ShapeRegistry();
$r->register('circle', fn() => new Circle());
$r->register('square', fn() => new Square());
echo $r->create('square')->name(), PHP_EOL; // square

ตรวจสอบอย่างรวดเร็ว

เลือกเครื่องมือสำหรับการสร้างที่เหมาะสมที่สุดสำหรับสถานการณ์นี้

สรุป

คุณควบคุมการสร้างอ็อบเจกต์ด้วยรูปแบบการสร้าง ได้แก่ โรงงานเพื่อซ่อนประเภทรูปธรรมและเลือกตระกูลผลิตภัณฑ์ ตัวสร้างเพื่อประกอบอ็อบเจกต์ที่ซับซ้อนอย่างต่อเนื่อง และซิงเกิลตันพร้อมข้อแลกเปลี่ยนของมัน บทเรียนสำคัญสำหรับแนวทางสมัยใหม่คือ เลือกใช้โรงงานและตัวสร้างได้อย่างอิสระ แต่แทนที่ซิงเกิลตันด้วยวงจรชีวิตอินสแตนซ์ร่วมของคอนเทนเนอร์ DI เพื่อให้การพึ่งพาชัดเจนและทดสอบได้

คำถามที่พบบ่อย

บทเรียน “รูปแบบการสร้าง: Factory, Builder, Singleton” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “รูปแบบการสร้าง: Factory, Builder, Singleton” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส PHP Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “รูปแบบการสร้าง: Factory, Builder, Singleton”

ควบคุมการสร้างออบเจ็กต์อย่างเป็นระเบียบด้วยรูปแบบการสร้าง คุณปฏิบัติ PHP Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน PHP Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน PHP Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “รูปแบบการสร้าง: Factory, Builder, Singleton” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน PHP Academy นี้ได้ไหม

ได้ บทเรียน PHP Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. หลักการ SOLID ในการใช้งานจริง
  2. รูปแบบการสร้าง: Factory, Builder, Singleton
  3. รูปแบบโครงสร้าง: Adapter, Decorator, Facade
  4. รูปแบบพฤติกรรม: Strategy, Observer, Command
← กลับไปที่ PHP Academy