1

I am a little bit confused about simple factory and factory method. My main difficult is the abrut difference between the examples code on the internet, even on wikipedia, where have lots of them, some with Interfaces, some with Switch cases and some even with registers

I've create this simple one example, using PHP, but I'am not confident if its can be considered a simple factory and/or factory method:

<?php

abstract class Log {
    protected $nome;     
    public function __construct(string $nome) {
        touch($nome);
        $this->nome = $nome;
    }

    protected function getDataHora(): string {
        return (new \DateTime())->format('Y-m-d h:I:s.v');
    }
    public abstract function insert(string $texto);
    public abstract function read(): string;
}

class TextLog extends Log {

    public function insert(string $texto) {
        $log_entry = $this->getDataHora() . ";" . $texto . PHP_EOL;
        file_put_contents($this->nome, $log_entry, FILE_APPEND | LOCK_EX);
    }

    public function read(): string {
        return file_get_contents($this->nome);
    }

}

class JsonLog extends Log {
    public function insert(string $texto) {
        $log_entry = ['data' => $this->getDataHora(), 'texto' => $texto];
        $json = file_get_contents($this->nome);
        $tempArray = json_decode($json, true);
        if(!is_array($tempArray)){
            $tempArray = [];
        }
        array_push($tempArray, $log_entry);
        $jsonData = json_encode($tempArray);
        file_put_contents($this->nome, $jsonData);
    }

    public function read(): string {
        $json = file_get_contents($this->nome);
        $array = json_decode($json);
        return implode(";", $array);
    }

}

class LogFactory {
    public static function get(string $tipo): Log {
        switch (strtoupper($tipo)) {
            default:
            case 'TXT':
                return new TextLog("log.txt");
            case 'JSON':
                return new JsonLog("log.json");
        }
    }
}
$log = LogFactory::get('txt');
var_dump($log);
$log->insert('Testando 1,2,3...');
4

1 Answer 1

4

Let's consider:

  • direct object creation,
  • simple factory,
  • factory method,
  • abstract factory

With direct object creation we have client code directly invoking some class constructors via new.  This creates a strong coupling between client code and the created classes.  Using the client with other classes means editing code of the client (cloning and forking the code), wherever their new operations occur.  (Assuming the client code could be abstract enough to be reused in another context especially in the same program, this editing would be undesirable.)

The simple factory hides the actual invocation — the new constructor instantiation — in a method that is not designed to be overridden or polymorphic-ally implemented.  As such, a simple factory is often a static method.  It trades the strong coupling between client and class (constructors) for a strong coupling between client and the static factory method.  One level of indirection to reduce the number of locations that would have to be edited in the client to change usage of one class to another.

The factory method pattern builds on this but adds the ability to re-implement the factory method through polymorphism.  Thus, there is a notion of a factory object that can be passed around as a parameter; there can be multiple/differing factory objects in the same program.  No editing of the client is necessary to use the client code with different objects to be created — instead, a polymorphic implementations of the factory can be created and the client code used with them.

The abstract factory pattern contains multiple implementations of the factory method so that a single abstract factory can create related classes that are not necessarily subclasses of each other.  It is simply an aggregation of multiple related but different factory method patterns.

None of these patterns mean much until we separate with some distance code that decides what to construct from code that merely constructs.  The latter can often be abstracted for reuse, provided that it does not accidentally hard code the decisions of what concrete classes to create.  (Creating a factory on one line of code and an object by the factory on the next, sort of defeats the whole concept and yet so many examples to be found do exactly that.)

Here's where dependency injection and inversion of control come in: the idea is to keep moving the choice of what classes to construct further away from the reusable client code whose algorithm(s) create objects using factories as parameters.

3
  • So your definition of a Factory Method is a "Simple Factory" with overloads? Commented Feb 4, 2020 at 22:59
  • @RobertHarvey, yes, if you will, it is upgraded from a simple static factory method, into an object to hold factory state, to differentiate from other factories, and to pass around to clients.
    – Erik Eidt
    Commented Feb 4, 2020 at 23:40
  • so @ErikEidt, I have created a new code, is it a "truly" factory method? 3v4l.org/ZcOmX
    – celsowm
    Commented Feb 6, 2020 at 15:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.