Can a GoF Builder implementation be considered valid without an explicit getProduct()?

For studying purpose, I’ve tried to create a simple PHP implementation of Builder GoF (not the Joshua Bloch’s one) inspired on this slide.

The main goal of this example is to encapsulate the construction of data files from diferents inputs (Directors) and outputs (Builders)

Lots of Builder example (including the wikipedia’s one) define an explicit “getProduct/getResult” on the Builder Class.

In my case, I thought the creation of output file would be considered the literal product, so I have opted to not use a method to get the file.

So, I would like to know if the absence of this method would invalidate it as Builder GoF implementation.

<?php
namespace BuilderGoFEnglish;
abstract class Builder {
    protected SplFileObject $output;
    public function __construct(string $outputFileName) {
        $this->output = new SplFileObject($outputFileName, 'w');
    }
    abstract function addHeader(array $header);
    abstract function addLine(array $linha);
    abstract function finish();
}
abstract class Director {
    protected Builder $builder;
    public function __construct(Builder $builder) {
        $this->builder = $builder;
    }
    public abstract function build(string $inputFileName);
}
class XmlDirector extends Director {
    public function build(string $inputFileName) {
        $document = new DOMDocument();
        $document->preserveWhiteSpace = false;
        $document->load($inputFileName);
        $root = $document->firstChild;
        $item1 = iterator_to_array($root->firstChild->childNodes);
        $this->builder->addHeader(array_column($item1, 'tagName'));
        foreach($root->childNodes as $child){
            $item = iterator_to_array($child->childNodes);
            $this->builder->addLine(array_column($item1, 'nodeValue'));
        }
        $this->builder->finish();
    }
}
class JsonDirector extends Director {
    public function build(string $inputFileName) {
        $jsonArray = json_decode(file_get_contents($inputFileName));
        $this->builder->addHeader(array_keys((array) $jsonArray[0]));
        foreach ($jsonArray as $jsonObject) {
            $this->builder->addLine((array) $jsonObject);
        }
        $this->builder->finish();
    }
}
class HtmlBuilder extends Builder {
    private DOMDocument $document;
    private DOMElement $table;
    public function __construct(string $output) {
        parent::__construct($output);
        $this->document = new DOMDocument('1.0', 'utf-8');
        $this->document->appendChild($this->document->createElement('html'));
        $this->table = $this->document->createElement('table');
        $this->table->setAttribute('border', 1);
        $this->document->firstChild->appendChild($this->table);
    }
    private function createTableRow(array $linha, $tipo = 'td'){
        $tr = $this->document->createElement('tr');
        array_map(fn($v) =>
                $tr->appendChild($this->document->createElement($tipo, $v)),
                $linha);
        $this->table->appendChild($tr);
    }
    public function addHeader(array $header) {
        $this->createTableRow($header, 'th');
    }
    public function addLine(array $linha) {
        $this->createTableRow($linha);
    }
    public function finish() {
        $this->output->fwrite($this->document->saveHTML());
    }
}
class CsvBuilder extends Builder {
    private array $csvArray = [];
    public function addHeader(array $header) {
        $this->csvArray[] = $header;
    }
    public function addLine(array $linha) {
        $this->csvArray[] = $linha;
    }
    public function finish() {
        foreach ($this->csvArray as $linha) {
            $this->output->fputcsv($linha);
        }
    }
}

Go to Source
Author: celsowm