lundi 30 mai 2022

OOP: factory method in abstract parent class?

I have the abstract class ChordPrinter with several children implementing it ChordPrinterEnglish, ChordPrinterSpanish):

abstract class ChordPrinter
{
    abstract public function printChordInNotation($fundamental, $attributes);

    //(other non-abstract methods)
}

Until now, I'd create an instance of a particular printer through a factory method provided by my framework's (Silex) dependency container:

$this['factory.ChordPrinter'] = $this->protect(function ($printer) {
    $printer = Domain\ChordPrinter\ChordPrinter::class . $printer;
    return new $printer();
});

In my new framework (Laravel) there's no such a thing as factories in the dependency container, so I have to make a factory of my own. I've thought of making a static method in the parent abstract class ChordPrinter:

abstract class ChordPrinter
{
    abstract public function printChordInNotation($fundamental, $attributes);

    //Is this the right place for this?
    public static function factory(string $printer): self
    {
        $printer = ChordPrinter::class . $printer;
        return new $printer();
    }
}

From an OOP point of view, is this the abstract class ChordPrinter the right place for the factory method? Not using the dependency container makes unit testing more difficult (it was easy to inject a mocked version of the factory into the DC). Other alternatives:

  1. Make a new class ChordPrinterFactory with a strategy pattern creating the concrete ChordPrinter* instances. But no easy mocking.
  2. Make a Laravel facade ChordPrinterFactory. Easy mocking.
  3. Do not make a factory, but duplicate those 2 lines in factory() every time I need a concrete instance of ChordPrinter.

Aucun commentaire:

Enregistrer un commentaire