Creational/Builder

This commit is contained in:
Yevhen Odynets 2025-07-04 02:23:11 +03:00
parent ab4499a305
commit 979ae42cde
7 changed files with 308 additions and 4 deletions

View File

@ -2,9 +2,7 @@
declare(strict_types = 1); declare(strict_types = 1);
use PhpCsFixer\Config; use PhpCsFixer\{Config, Finder, Runner\Parallel\ParallelConfigFactory};
use PhpCsFixer\Finder;
use PhpCsFixer\Runner\Parallel\ParallelConfigFactory;
$finder = (new Finder())->in([ $finder = (new Finder())->in([
__DIR__ . '/src', __DIR__ . '/src',

43
code/builder.php Normal file
View File

@ -0,0 +1,43 @@
<?php
/**
* @package: patterns
* @author: Yevhen Odynets
* @date: 2025-07-04
* @time: 00:19
*/
declare(strict_types = 1);
use Pattern\Creational\Builder\BigMacBuilder;
use Pattern\Creational\Builder\Director;
/**
* The client code creates a builder object, passes it to the director and then
* initiates the construction process. The end result is retrieved from the
* builder object.
*
* @noinspection ForgottenDebugOutputInspection*/
function clientCode(Director $director): void
{
$builder = new BigMacBuilder();
$director->setBuilder($builder);
echo 'Preparing full featured Big Mac...';
$director->regularBigMac();
dump($builder->getBigMac()->getIngredients());
echo 'Preparing vegan Big Mac...';
$director->veganBigMac();
dump($builder->getBigMac()->getIngredients());
// The Builder pattern can be used without a Director class.
echo 'Preparing a custom snack...';
$builder->produceBun();
$builder->produceMeat();
$builder->produceSauce();
dump($builder->getBigMac()->getIngredients());
}
clientCode(new Director());

View File

@ -0,0 +1,40 @@
<?php
/**
* @package: patterns
* @author: Yevhen Odynets
* @date: 2025-07-04
* @time: 00:21
*/
declare(strict_types = 1);
namespace Pattern\Creational\Builder;
class BigMac
{
/**
* @var array
*/
private array $ingredients = [];
/**
* @param string $ingredient
*
* @return $this
*/
public function setIngredient(string $ingredient): static
{
$this->ingredients[] = $ingredient;
return $this;
}
/**
* @return array
*/
public function getIngredients(): array
{
return $this->ingredients;
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* @package: patterns
* @author: Yevhen Odynets
* @date: 2025-07-04
* @time: 00:42
*/
declare(strict_types = 1);
namespace Pattern\Creational\Builder;
/**
* The BigMac Builder classes follow the BigMacBuilderInterface interface and provide
* specific implementations of the building steps. The program may have several
* variations of BigMac Builders, implemented differently.
*/
class BigMacBuilder implements BigMacBuilderInterface
{
private BigMac $bigMac;
/**
* A fresh builder instance should contain a blank BigMac object, which is
* used in further assembly.
*/
public function __construct()
{
$this->reset();
}
public function reset(): void
{
$this->bigMac = new BigMac();
}
/**
* All production steps work with the same BigMac instance.
*/
public function produceBun(): void
{
$this->bigMac->setIngredient('A three-slice sesame seed bun');
}
public function produceVeganBun(): void
{
$this->bigMac->setIngredient('A three-slice dairy-free bun');
}
public function produceMeat(): void
{
$this->bigMac->setIngredient('Two 1.6 oz beef patties');
}
public function produceVeganMeat(): void
{
$this->bigMac->setIngredient('Two plant-based burgers, like Impossible Burgers or Pureland Farm Burgers');
}
public function produceSauce(): void
{
$this->bigMac->setIngredient('"special sauce" (similar to Thousand Island dressing)');
}
public function produceVeganSauce(): void
{
$this->bigMac->setIngredient('Vegan special sauce');
}
public function produceLettuce(): void
{
$this->bigMac->setIngredient('Shredded iceberg lettuce');
}
public function produceCheese(): void
{
$this->bigMac->setIngredient('One slice of processed American cheese');
}
public function produceVeganCheese(): void
{
$this->bigMac->setIngredient('One slice of vegan American or cheddar cheese');
}
public function producePickles(): void
{
$this->bigMac->setIngredient('Two dill pickle slices');
}
public function produceOnions(): void
{
$this->bigMac->setIngredient('Minced onions');
}
/**
* MigMac Builders are supposed to provide their own methods for
* retrieving results. That's because various types of builders may create
* entirely different BigMacs that don't follow the same interface.
* Therefore, such methods cannot be declared in the base Builder interface
* (at least in a statically typed programming language). Note that PHP is a
* dynamically typed language and this method CAN be in the base interface.
* However, we won't declare it there for the sake of clarity.
*
* Usually, after returning the end result to the client, a builder instance
* is expected to be ready to start producing another BigMac. That's why
* it's a usual practice to call the reset method at the end of the
* `getBigMac` method body. However, this behavior is not mandatory, and
* you can make your builders wait for an explicit reset call from the
* client code before disposing of the previous result.
*/
public function getBigMac(): BigMac
{
$result = $this->bigMac;
$this->reset();
return $result;
}
}

View File

@ -0,0 +1,41 @@
<?php
/**
* @package: patterns
* @author: Yevhen Odynets
* @date: 2025-07-04
* @time: 00:32
*/
declare(strict_types = 1);
namespace Pattern\Creational\Builder;
/**
* The BigMacBuilderInterface specifies methods for creating the different parts of
* the BigMac objects.
*/
interface BigMacBuilderInterface
{
public function produceBun(): void;
public function produceVeganBun(): void;
public function produceMeat(): void;
public function produceVeganMeat(): void;
public function produceSauce(): void;
public function produceVeganSauce(): void;
public function produceLettuce(): void;
public function produceCheese(): void;
public function produceVeganCheese(): void;
public function producePickles(): void;
public function produceOnions(): void;
}

View File

@ -0,0 +1,62 @@
<?php
/**
* @package: patterns
* @author: Yevhen Odynets
* @date: 2025-07-04
* @time: 01:49
*/
declare(strict_types = 1);
namespace Pattern\Creational\Builder;
/**
* The Director is only responsible for executing the building steps in a
* particular sequence. It is helpful when producing Big Macs according to a
* specific order or configuration. Strictly speaking, the Director class is
* optional, since the client can control builders directly.
*/
class Director
{
/**
* @var BigMacBuilder
*/
private BigMacBuilder $builder;
/**
* The Director works with any builder instance that the client code passes
* to it. This way, the client code may alter the final type of the newly
* assembled product.
*/
public function setBuilder(BigMacBuilder $builder): void
{
$this->builder = $builder;
}
/**
* The Director can construct several product variations using the same
* building steps.
*/
public function regularBigMac(): void
{
$this->builder->produceBun();
$this->builder->produceMeat();
$this->builder->produceSauce();
$this->builder->produceLettuce();
$this->builder->produceCheese();
$this->builder->producePickles();
$this->builder->produceOnions();
}
public function veganBigMac(): void
{
$this->builder->produceVeganBun();
$this->builder->produceVeganMeat();
$this->builder->produceVeganSauce();
$this->builder->produceLettuce();
$this->builder->produceVeganCheese();
$this->builder->producePickles();
$this->builder->produceOnions();
}
}

View File

@ -9,6 +9,8 @@
declare(strict_types = 1); declare(strict_types = 1);
use Random\RandomException;
/** /**
* @param ...$vars * @param ...$vars
* *
@ -36,7 +38,7 @@ function trace(): string
} }
/** /**
* @throws \Random\RandomException * @throws RandomException
*/ */
function getFloatRange(): float function getFloatRange(): float
{ {