DEV Community

Cover image for Factory Method Design Pattern Explained with PHP Examples
Hòa Nguyễn Coder
Hòa Nguyễn Coder

Posted on

1

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

Image of Docusign

Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

Cloudinary image

Video API: manage, encode, and optimize for any device, channel or network condition. Deliver branded video experiences in minutes and get deep engagement insights.

Learn more

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay