Factory Method Design Pattern Explained with PHP Examples

skipperhoa

Hòa Nguyễn Coder

Posted on November 30, 2024

Factory Method Design Pattern Explained with PHP Examples

Factory Method Design Pattern Explained with PHP Examples

🚀 The acticle 🧑‍💻

🚀 Link Github🧑‍💻
😉 I hope you’ll support and follow me for more useful knowledge sharing!

Subscribe to Hòa Nguyễn Coder's YouTube channel

Facetory is a but in Creational Design Patterns, help create object , don't need specify class

Instead of create object using new , Facetory Method using a method special in class or interface ,after then return object

Purpose

  • Provides flexibility to add new classes without changing existing source code

  • Increase Scalability (open/closed Principle)

  • Separate object initialzation logic from main business logic

Factory Method Structure

  • Product : Interface or abstract class defines the objects that are created

  • Concrete Product : Concrete classes that implement or extends from Product

  • Creator : The class or Interface definde a facetoryMethod method that returns Product

  • Concrete creator : Concrete class implmenting the method facetoryMethod to create the Concrete Product

Example

  • Product class initialztation

interface Logger {
    public function log(string $message): void;
}

class FileLogger implements Logger {
    public function log(string $message): void {
        echo "Logging to a file: $message";
    }
}

class DatabaseLogger implements Logger {
    public function log(string $message): void {
        echo "Logging to a database: $message";
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Creator and Concrete Creator

abstract class LoggerFactory {
    // Phương thức factory method
    abstract public function createLogger(): Logger;

    public function log(string $message): void {
        $logger = $this->createLogger();
        $logger->log($message);
    }
}

class FileLoggerFactory extends LoggerFactory {
    public function createLogger(): Logger {
        return new FileLogger();
    }
}

class DatabaseLoggerFactory extends LoggerFactory {
    public function createLogger(): Logger {
        return new DatabaseLogger();
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Ussing Facetory Method
// Tạo logger dạng File
$fileLoggerFactory = new FileLoggerFactory();
$fileLoggerFactory->log("This is a file log message.");

// Tạo logger dạng Database
$databaseLoggerFactory = new DatabaseLoggerFactory();
$databaseLoggerFactory->log("This is a database log message.");

Enter fullscreen mode Exit fullscreen mode

Advantages of Factory Method

  • Scalable : create a new product, only need add product class and creator class respectively

  • Reuse : same business logic, but different objects can be created without modifying the main source code.

  • Separation of responsibilities : creator is responsible for object initialization , initialization logic is not part of business logic

Disadvantages

  • the code more complicated, because it requires additional creator class and Concrete Product classes

  • Ability extends ,requires the initial design to be accurate

Example 2: CRUD (User and Role) in PHP

  • Setup interface

interface CrudInterface {
    public function create(array $data): void;
    public function read(int $id): ?array;
    public function update(int $id, array $data): void;
    public function delete(int $id): void;
}
Enter fullscreen mode Exit fullscreen mode
  • Product (User Role)
class User implements CrudInterface {
    private $users = []; // Mô phỏng cơ sở dữ liệu

    public function create(array $data): void {
        $this->users[$data['id']] = $data;
        echo "User created: " . json_encode($data) . PHP_EOL;
    }

    public function read(int $id): ?array {
        return $this->users[$id] ?? null;
    }

    public function update(int $id, array $data): void {
        if (isset($this->users[$id])) {
            $this->users[$id] = array_merge($this->users[$id], $data);
            echo "User updated: " . json_encode($this->users[$id]) . PHP_EOL;
        } else {
            echo "User not found." . PHP_EOL;
        }
    }

    public function delete(int $id): void {
        unset($this->users[$id]);
        echo "User deleted: $id" . PHP_EOL;
    }
}

class Role implements CrudInterface {
    private $roles = []; // Mô phỏng cơ sở dữ liệu

    public function create(array $data): void {
        $this->roles[$data['id']] = $data;
        echo "Role created: " . json_encode($data) . PHP_EOL;
    }

    public function read(int $id): ?array {
        return $this->roles[$id] ?? null;
    }

    public function update(int $id, array $data): void {
        if (isset($this->roles[$id])) {
            $this->roles[$id] = array_merge($this->roles[$id], $data);
            echo "Role updated: " . json_encode($this->roles[$id]) . PHP_EOL;
        } else {
            echo "Role not found." . PHP_EOL;
        }
    }

    public function delete(int $id): void {
        unset($this->roles[$id]);
        echo "Role deleted: $id" . PHP_EOL;
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Create Factory class

abstract class CrudFactory {
    abstract public function createCrud(): CrudInterface;
}

class UserFactory extends CrudFactory {
    public function createCrud(): CrudInterface {
        return new User();
    }
}

class RoleFactory extends CrudFactory {
    public function createCrud(): CrudInterface {
        return new Role();
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Factory Method use CRUD
// Factory cho User
$userFactory = new UserFactory();
$userCrud = $userFactory->createCrud();

// Thực hiện các thao tác CRUD cho User
$userCrud->create(['id' => 1, 'name' => 'Hoa Dev', 'email' => 'hoadev@example.com']);
$userCrud->update(1, ['email' => 'hoadev.code@example.com']);
$userData = $userCrud->read(1);
echo "Read User: " . json_encode($userData) . PHP_EOL;
$userCrud->delete(1);

// Factory cho Role
$roleFactory = new RoleFactory();
$roleCrud = $roleFactory->createCrud();

// Thực hiện các thao tác CRUD cho Role
$roleCrud->create(['id' => 101, 'name' => 'Admin']);
$roleCrud->update(101, ['name' => 'Super Admin']);
$roleData = $roleCrud->read(101);
echo "Read Role: " . json_encode($roleData) . PHP_EOL;
$roleCrud->delete(101);
Enter fullscreen mode Exit fullscreen mode
  • Results 👍
User created: {"id":1,"name":"Hoa Dev","email":"hoadev@example.com"}
User updated: {"id":1,"name":"Hoa Dev","email":"hoadev.code@example.com"}
Read User: {"id":1,"name":"Hoa Dev","email":"hoadev.code@example.com"}
User deleted: 1
Role created: {"id":101,"name":"Admin"}
Role updated: {"id":101,"name":"Super Admin"}
Read Role: {"id":101,"name":"Super Admin"}
Role deleted: 101

Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
skipperhoa
Hòa Nguyễn Coder

Posted on November 30, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related