Kotchasan PHP Framework

การใช้ Design Patterns ในภาษา PHP

Design Patterns คือแนวทางในการออกแบบและแก้ไขปัญหาที่เกิดขึ้นซ้ำๆ ในการเขียนโปรแกรม โดยมีรูปแบบที่ได้รับการพิสูจน์ว่ามีประสิทธิภาพและใช้ได้ผลดี Design Patterns สามารถแบ่งออกเป็น 3 กลุ่มใหญ่ คือ Creational Patterns, Structural Patterns, และ Behavioral Patterns บทความนี้จะอธิบายตัวอย่างของ Pattern เหล่านี้ในภาษา PHP

1. Creational Patterns

Creational Patterns มุ่งเน้นที่การจัดการวิธีการสร้างวัตถุ โดยไม่ต้องสร้างวัตถุขึ้นโดยตรง แต่ใช้วิธีการที่มีประสิทธิภาพมากกว่า ตัวอย่างที่สำคัญ ได้แก่

1.1 Singleton Pattern

Singleton Pattern เป็นการสร้างวัตถุเพียงตัวเดียวในแอปพลิเคชัน และใช้วัตถุนี้ตลอดการทำงานของระบบ เช่น การเชื่อมต่อฐานข้อมูล

class Singleton {
    private static $instance;

    private function __construct() {}
    
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new Singleton();
        }
        return self::$instance;
    }
}

1.2 Factory Pattern

Factory Pattern ใช้เพื่อสร้างวัตถุจากหลายคลาสโดยไม่ต้องระบุชนิดของวัตถุล่วงหน้า

class ProductFactory {
    public static function create($type) {
        if ($type === 'A') {
            return new ProductA();
        } elseif ($type === 'B') {
            return new ProductB();
        }
        throw new Exception("Invalid product type");
    }
}

1.3 Abstract Factory Pattern

Abstract Factory Pattern ขยายจาก Factory Pattern โดยช่วยสร้างวัตถุจากหลายคลาสในตระกูลเดียวกัน

interface GUIFactory {
    public function createButton();
}

class WinFactory implements GUIFactory {
    public function createButton() {
        return new WinButton();
    }
}

class MacFactory implements GUIFactory {
    public function createButton() {
        return new MacButton();
    }
}

1.4 Builder Pattern

Builder Pattern แยกการสร้างวัตถุที่ซับซ้อนออกเป็นส่วนย่อย ๆ ทำให้การสร้างมีความยืดหยุ่นมากขึ้น

class Car {
    private $engine;
    private $wheels;
    
    public function setEngine($engine) {
        $this->engine = $engine;
    }

    public function setWheels($wheels) {
        $this->wheels = $wheels;
    }
}

class CarBuilder {
    private $car;
    
    public function __construct() {
        $this->car = new Car();
    }
    
    public function addEngine($engine) {
        $this->car->setEngine($engine);
    }

    public function addWheels($wheels) {
        $this->car->setWheels($wheels);
    }

    public function build() {
        return $this->car;
    }
}

1.5 Prototype Pattern

Prototype Pattern ใช้ในการสร้างวัตถุใหม่โดยการคัดลอกวัตถุเดิม (cloning)

class Prototype {
    public $name;
    
    public function __clone() {
        // โคลนวัตถุ
    }
}

$prototype = new Prototype();
$clone = clone $prototype;

2. Structural Patterns

Structural Patterns เน้นการจัดการโครงสร้างของวัตถุและการเชื่อมต่อระหว่างคลาส ตัวอย่างสำคัญของ Structural Patterns ได้แก่

2.1 Adapter Pattern

Adapter Pattern ช่วยให้คลาสต่างกันสามารถทำงานร่วมกันได้โดยการปรับอินเตอร์เฟซของคลาสหนึ่งให้เข้ากับอีกคลาสหนึ่ง

interface MediaPlayer {
    public function play($filename);
}

class MP3Player implements MediaPlayer {
    public function play($filename) {
        echo "Playing MP3 file: " . $filename;
    }
}

class MP4Adapter implements MediaPlayer {
    private $mp4Player;

    public function __construct(MP4Player $mp4Player) {
        $this->mp4Player = $mp4Player;
    }

    public function play($filename) {
        $this->mp4Player->playMP4($filename);
    }
}

2.2 Facade Pattern

Facade Pattern ช่วยซ่อนความซับซ้อนของระบบโดยสร้างอินเตอร์เฟซที่ง่ายสำหรับผู้ใช้งาน

class CPU {
    public function start() {
        echo "CPU started.";
    }
}

class Memory {
    public function load() {
        echo "Memory loaded.";
    }
}

class HardDrive {
    public function read() {
        echo "Hard drive reading data.";
    }
}

class ComputerFacade {
    private $cpu;
    private $memory;
    private $hardDrive;

    public function __construct() {
        $this->cpu = new CPU();
        $this->memory = new Memory();
        $this->hardDrive = new HardDrive();
    }

    public function start() {
        $this->cpu->start();
        $this->memory->load();
        $this->hardDrive->read();
    }
}

2.3 Composite Pattern

Composite Pattern ใช้ในการจัดการวัตถุหลายตัวที่มีลักษณะเหมือนกันในโครงสร้างแบบต้นไม้

interface Component {
    public function operation();
}

class Leaf implements Component {
    public function operation() {
        echo "Leaf operation\n";
    }
}

class Composite implements Component {
    private $children = [];

    public function add(Component $component) {
        $this->children[] = $component;
    }

    public function operation() {
        foreach ($children as $child) {
            $child->operation();
        }
    }
}

2.4 Decorator Pattern

Decorator Pattern ช่วยเพิ่มฟังก์ชันให้วัตถุโดยไม่ต้องแก้ไขโค้ดเดิมของวัตถุ

interface Coffee {
    public function cost();
}

class SimpleCoffee implements Coffee {
    public function cost() {
        return 50;
    }
}

class MilkDecorator implements Coffee {
    protected $coffee;

    public function __construct(Coffee $coffee) {
        $this->coffee = $coffee;
    }

    public function cost() {
        return $this->coffee->cost() + 20;
    }
}

2.5 Proxy Pattern

Proxy Pattern เป็นตัวแทนที่ควบคุมการเข้าถึงวัตถุจริง เช่น ใช้ในการทำ caching หรือ logging

interface Image {
    public function display();
}

class RealImage implements Image {
    private $filename;

    public function __construct($filename) {
        $this->filename = $filename;
        $this->loadFromDisk();
    }

    private function loadFromDisk() {
        echo "Loading " . $this->filename . "\n";
    }

    public function display() {
        echo "Displaying " . $this->filename . "\n";
    }
}

class ProxyImage implements Image {
    private $realImage;
    private $filename;

    public function __construct($filename) {
        $this->filename = $filename;
    }

    public function display() {
        if ($this->realImage === null) {
            $this->realImage = new RealImage($this->filename);
        }
        $this->realImage->display();
    }
}

3. Behavioral Patterns

Behavioral Patterns มุ่งเน้นการจัดการการสื่อสารและปฏิสัมพันธ์ระหว่างวัตถุต่าง ๆ ตัวอย่าง Behavioral Patterns ได้แก่

3.1 Observer Pattern

Observer Pattern ช่วยให้วัตถุสามารถแจ้งเตือนวัตถุอื่นเมื่อมีการเปลี่ยนแปลงสภาพภายใน

class Subject {
    private $observers = [];

    public function addObserver($observer) {
        $this->observers[] = $observer;
    }

    public function notifyObservers() {
        foreach ($this->observers as $observer) {
            $observer->update();
        }
    }
}

class ConcreteObserver {
    public function update() {
        echo "Observer notified!\n";
    }
}

3.2 Strategy Pattern

Strategy Pattern ช่วยให้สามารถเปลี่ยนวิธีการทำงานของวัตถุได้ใน runtime โดยกำหนดกลยุทธ์ที่แตกต่างกัน

interface Strategy {
    public function execute($a, $b);
}

class AddStrategy implements Strategy {
    public function execute($a, $b) {
        return $a + $b;
    }
}

3.3 Command Pattern

Command Pattern ใช้ในการแยกคำสั่งออกจากผู้เรียกใช้และผู้ปฏิบัติคำสั่ง ทำให้คำสั่งสามารถยกเลิกหรือบันทึกได้ง่าย

interface Command {
    public function execute();
}

class Light {
    public function turnOn() {
        echo "Light is on\n";
    }
}

class TurnOnCommand implements Command {
    private $light;

    public function __construct(Light $light) {
        $this->light = $light;
    }

    public function execute() {
        $this->light->turnOn();
    }
}

3.4 Chain of Responsibility Pattern

Chain of Responsibility Pattern ส่งคำร้องผ่านลำดับของวัตถุที่มีความรับผิดชอบในคำร้องนั้น

abstract class Handler {
    protected $nextHandler;

    public function setNext(Handler $handler) {
        $this->nextHandler = $handler;
        return $handler;
    }

    public function handle($request) {
        if ($this->nextHandler) {
            $this->nextHandler->handle($request);
        }
    }
}

3.5 Mediator Pattern

Mediator Pattern ใช้วัตถุตัวกลางจัดการการสื่อสารระหว่างวัตถุต่าง ๆ โดยทำให้วัตถุไม่ต้องสื่อสารกันโดยตรง

interface Mediator {
    public function send($message, Colleague $colleague);
}

บทสรุป

การใช้ Design Patterns ในภาษา PHP ช่วยทำให้โค้ดของคุณมีความเป็นระเบียบ มีความยืดหยุ่น และง่ายต่อการดูแลรักษา โดยการเลือกใช้ Pattern ที่เหมาะสมกับสถานการณ์และโครงสร้างของโปรเจกต์จะช่วยเพิ่มประสิทธิภาพในการพัฒนาและความสามารถในการขยายโปรเจกต์ในอนาคต

การศึกษาและเข้าใจ Design Patterns ต่าง ๆ จะทำให้คุณเป็นนักพัฒนาที่สามารถเขียนโค้ดได้มีประสิทธิภาพและมีความสามารถในการแก้ปัญหาได้อย่างเป็นระบบมากขึ้น