PHP - 設計模式

Hello, aspiring programmers! I'm thrilled to embark on this journey with you into the fascinating world of PHP design patterns. As your guide, I'll use my years of teaching experience to break down these concepts in a way that's easy to understand, even if you've never written a line of code before. So, let's dive in!

PHP - Design Patterns

什麼是設計模式?

Before we delve into specific patterns, let's understand what design patterns are. Imagine you're building a house. You wouldn't start from scratch every time, right? You'd use tried-and-tested blueprints. Design patterns are like these blueprints for software development. They're reusable solutions to common problems that developers face.

Now, let's explore some key design patterns in PHP.

Singleton Pattern

什麼是 Singleton Pattern?

The Singleton pattern ensures that a class has only one instance and provides a global point of access to it. It's like having a single, special key that opens a very important door, and everyone who needs to use that door must use that same key.

當什麼時候使用它?

Use the Singleton pattern when:

  • Exactly one instance of a class is needed
  • You want to control access to a shared resource

代碼範例

class Database {
private static $instance = null;
private $connection;

private function __construct() {
$this->connection = new PDO("mysql:host=localhost;dbname=mydb", "username", "password");
}

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

public function query($sql) {
return $this->connection->query($sql);
}
}

// 使用
$db1 = Database::getInstance();
$db2 = Database::getInstance();

// $db1 和 $db2 是同一個實例

在這個例子中,我們創建了一個只能有一個實例的 Database 類別。getInstance() 方法檢查是否已經存在一個實例。如果沒有,它會創建一個;否則,它會返回已存在的實例。

Factory Pattern

什麼是 Factory Pattern?

The Factory pattern is like a manufacturing plant. Instead of creating objects directly, we use a factory method to create them. This allows for flexibility in object creation and decouples the creation logic from the main code.

當什麼時候使用它?

Use the Factory pattern when:

  • The type of objects you need to create is determined at runtime
  • You want to centralize the creation logic of related objects

代碼範例

interface Animal {
public function speak();
}

class Dog implements Animal {
public function speak() {
return "Woof!";
}
}

class Cat implements Animal {
public function speak() {
return "Meow!";
}
}

class AnimalFactory {
public static function createAnimal($type) {
switch($type) {
case 'dog':
return new Dog();
case 'cat':
return new Cat();
default:
throw new Exception("Invalid animal type");
}
}
}

// 使用
$dog = AnimalFactory::createAnimal('dog');
echo $dog->speak(); // 輸出: Woof!

$cat = AnimalFactory::createAnimal('cat');
echo $cat->speak(); // 輸出: Meow!

在這裡,我們有一個 AnimalFactory,它創建不同類型的動物。這讓我們可以輕鬆地添加新的動物類型,而不需要改變客戶端代碼。

Strategy Pattern

什麼是 Strategy Pattern?

The Strategy pattern allows you to define a family of algorithms, encapsulate each one, and make them interchangeable. It's like having different routes to reach a destination and being able to switch between them based on traffic conditions.

當什麼時候使用它?

Use the Strategy pattern when:

  • You have multiple algorithms for a specific task
  • You want to be able to switch between these algorithms dynamically

代碼範例

interface SortStrategy {
public function sort(array $data): array;
}

class BubbleSort implements SortStrategy {
public function sort(array $data): array {
// Bubble sort implementation
return $data;
}
}

class QuickSort implements SortStrategy {
public function sort(array $data): array {
// Quick sort implementation
return $data;
}
}

class Sorter {
private $sortStrategy;

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

public function sort(array $data): array {
return $this->sortStrategy->sort($data);
}
}

// 使用
$data = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];

$bubbleSorter = new Sorter(new BubbleSort());
$bubbleSorted = $bubbleSorter->sort($data);

$quickSorter = new Sorter(new QuickSort());
$quickSorted = $quickSorter->sort($data);

在這個例子中,我們可以輕鬆地在不同的排序算法之間切換,而不需要改變客戶端代碼。

MVC Design Pattern

什麼是 MVC Pattern?

MVC stands for Model-View-Controller. It's a architectural pattern that separates an application into three main components:

  • Model: Manages data and business logic
  • View: Handles the display of data
  • Controller: Acts as an intermediary between Model and View

當什麼時候使用它?

Use the MVC pattern when:

  • You want to separate concerns in your application
  • You need to make your code more maintainable and scalable

代碼範例

// Model
class UserModel {
public function getUsers() {
// Code to fetch users from database
return ['Alice', 'Bob', 'Charlie'];
}
}

// View
class UserView {
public function showUsers($users) {
echo "<ul>";
foreach ($users as $user) {
echo "<li>$user</li>";
}
echo "</ul>";
}
}

// Controller
class UserController {
private $model;
private $view;

public function __construct() {
$this->model = new UserModel();
$this->view = new UserView();
}

public function showUsers() {
$users = $this->model->getUsers();
$this->view->showUsers($users);
}
}

// 使用
$controller = new UserController();
$controller->showUsers();

這個例子展示了簡單的 MVC 構架。Controller 從 Model 獲取數據並將其傳遞給 View 進行顯示。

Summary of Design Patterns

Here's a quick reference table of the design patterns we've discussed:

Pattern Purpose Key Benefit
Singleton Ensure a class has only one instance Controls access to shared resources
Factory Create objects without specifying their exact class Flexibility in object creation
Strategy Define a family of interchangeable algorithms Allows switching algorithms at runtime
MVC Separate application logic into three components Improves maintainability and scalability

Remember, these patterns are tools in your programming toolkit. Like any tool, they're most effective when used in the right situation. As you gain more experience, you'll develop an intuition for when and how to apply them.

I hope this tutorial has given you a solid foundation in PHP design patterns. Keep practicing, stay curious, and happy coding!

Credits: Image by storyset