Skip to content

About a simple php example about the creational pattern: Factory Method

Notifications You must be signed in to change notification settings

willavelar/php-design-pattern-creational-factory-method

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Factory Method

Factory Method is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.


We need to create a log abstraction, which can be changed either to print on the screen or via file.

The problem

If we do it this way, every time we need to change how logging is done, we will need to change the LogManager class, thus violating SOLID's open/closed concept.

<?php
interface LogWritter
{
    public function write(string $formattedMessage) : void;
}
<?php
class StdoutLogWritter implements LogWritter
{
    public function write(string $formattedMessage): void
    {
        fwrite(STDOUT, $formattedMessage);
    }
}
<?php
class FileLogWritter implements LogWritter
{
    private $file;
    public function __construct(string $pathFile)
    {
        $this->file = fopen($pathFile, 'a+');
    }

    public function write(string $formattedMessage): void
    {
        fwrite($this->file, $formattedMessage);
    }

    public function __destruct()
    {
        fclose($this->file);
    }
}
<?php
class LogManager
{
    public function log(string $severity, string $mesage)
    {
        $logWritter = $this->createLogWritter();

        $today = new \DateTime();
        $formattedMessage = sprintf("[%s][%s]: %s", $today->format('d/m/Y'), $severity, $mesage);

        $logWritter->write($formattedMessage);

    }

    private function createLogWritter() : LogWritter
    {
        return new StdoutLogWritter();
    }
}
<?php
$logManager = new LogManager();
$logManager->log('INFO','Testing log manager');

The solution

Now, using the Factory Method pattern, we are able to create classes that will inherit from the FileManager, thus removing the responsibility for changing it, leaving us to just implement it.

<?php
abstract class LogManager
{
    public function log(string $severity, string $mesage)
    {
        $logWritter = $this->createLogWritter();

        $today = new \DateTime();
        $formattedMessage = sprintf("[%s][%s]: %s", $today->format('d/m/Y'), $severity, $mesage);

        $logWritter->write($formattedMessage);

    }

    abstract protected function createLogWritter() : LogWritter;
}
<?php
class StdoutLogManager extends LogManager
{
    protected function createLogWritter(): LogWritter
    {
        return new StdoutLogWritter();
    }
}
<?php
class FileLogManager extends LogManager
{
    private string $filePath;

    /**
     * @param string $filePath
     */
    public function __construct(string $filePath)
    {
        $this->filePath = $filePath;
    }

    protected function createLogWritter(): LogWritter
    {
        return new FileLogWritter($this->filePath);
    }
}
<?php
$logManager = new StdoutLogManager();
$logManager->log('INFO','Testing log manager');

$logManager = new FileLogManager(__DIR__. '/log.log');
$logManager->log('INFO','Testing log manager');

Installation for test

PHP Version Support Composer Version Support

composer install
php wrong/test.php
php right/test.php

About

About a simple php example about the creational pattern: Factory Method

Topics

Resources

Stars

Watchers

Forks

Languages