Pencil.php
<?php
class Pencil implements PencilInterface
{
protected ColorInterface $color;
public function __construct(ColorInterface $color)
{
$this->color = $color;
}
public function getColor(): ColorInterface
{
return $this->color;
}
}
PencilInterface.php
<?php
interface PencilInterface
{
public function getColor(): ColorInterface;
}
ColorInterface.php
<?php
interface ColorInterface
{
public function getValue(): string;
}
Color.php
<?php
class Color implements ColorInterface
{
public function __construct($value)
{
$this->value = $value;
}
public function setValue(string $value)
{
$this->value = $value;
}
public function getValue(): string
{
return $this->value;
}
}
$color = new Color('red');
$firstPencil = new Pencil($color);
$clonedPencil = clone $firstPencil;
$color->setValue('green');
echo $clonedPencil->getColor()->getValue(); // -> 'green'
echo $firstPencil->getColor()->getValue(); // -> 'green'
Pencil.php
<?php
class Pencil implements PencilInterface
{
protected ColorInterface $color;
public function __construct(ColorInterface $color)
{
$this->color = $color;
}
public function getColor(): ColorInterface
{
return $this->color;
}
public function __clone()
{
$this->color = clone $this->color;
}
}
$color = new Color('red');
$firstPencil = new Pencil($color);
$clonedPencil = clone $firstPencil;
$color->setValue('green');
echo $clonedPencil->getColor()->getValue(); // -> 'red'
echo $firstPencil->getColor()->getValue(); // -> 'green'
<?php
class PencilPoolFactory
{
/**
* ColorInterface[]
*/
protected array $colors = array();
public function has(string $key)
{
return isset($this->colors[$key]);
}
public function get(string $colorValue): ColorInterface
{
return $this->colors[$colorValue];
}
public function add(ColorInterface $color, string $colorValue)
{
$this->colors[$colorValue] = $color;
}
public function create(string $colorValue)
{
if (!$this->has($colorValue)) {
$this->add(new Color($colorValue), $colorValue);
}
return new Pencil($this->get($colorValue));
}
}
$pencilPoolFactory = new PencilPoolFactory();
$redPencil = $pencilPoolFactory->create('red');
$greenPencil = $pencilPoolFactory->create('green');
echo $redPencil->getColor()->getValue(); // 'red'
echo $greenPencil->getColor()->getValue(); // 'red'
🧙♂️️Le PencilPoolFactory mélange deux design patterns mais cela produit un mauvais pattern (le mot antipattern est un peu trop populaire et désigne aujourd'hui des choses eux-mêmes populaires).
D'une première raison : ce PencilPoolFactory fabrique des instances de Color ET des instances de Pencil, il a donc deux responsabilités, ce n'est pas la faute de la combinaison des deux design patterns.
D'une deuxième raison : le PencilPoolFactory garde en mémoire les instances de Color, ce qui lui donne une nouvelle responsabilité car l'utilisateur sera tenté de faire également un $pencilPoolFactory->get('color').
PencilFactory.php
<?php
class PencilFactory
{
PencilPoolInterface $pencilPool;
public function __construct(
PencilPoolInterface $pencilPool
)
{
$this->pencilPool = $pencilPool
}
public function create(string $colorValue): PencilInterface
{
$color = $this->pencilPool->get($colorValue);
return new Pencil($color);
}
protected function getColor(string $colorValue): ColorInterface
{
return $this->pencilPool->get($colorValue);
}
}
PencilPool.php
<?php
class PencilPool implements PencilPoolInterface
{
/**
* ColorInterface[]
*/
protected array $colors = array();
public function has(string $key)
{
return isset($this->colors[$key]);
}
public function get(string $colorValue): ColorInterface
{
return $this->colors[$colorValue];
}
public function add(ColorInterface $color, string $colorValue)
{
$this->colors[$colorValue] = $color;
}
}
PencilFactory.php
<?php
class PencilFactory implements PencilFactoryInterface
{
protected PencilPool $pencilPool;
public function create(string $colorValue)
{
if (!($pencilPool->has($colorValue)) {
$color = new Color($colorValue);
$pencilPool->set($color, $colorValue);
} else {
$color = $pencilPool->get($colorValue);
}
return $color;
}
}
<?php
class Singleton
{
private static $mySelf = null;
private function __construct(){} // Empêche toute création d'instance.
private function __clone(){} // Empêche toute copie d'instance.
public static function getInstance()
{
if (self::$mySelf === null) {
self::$mySelf = new Singleton();
}
return self::$mySelf;
}
}
<?php
$firstSingleton = Singleton::getInstance();
$secondSingleton = Singleton::getInstance();
class Singleton
{
}
class SingletonMaker
{
private static $singleton = null;
public static function getSingleton()
{
if (self::$singleton === null) {
self::$singleton = new Singleton();
}
return self::$singleton;
}
}
<?php
$firstSingleton = SingletonMaker::getSingleton();
$secondSingleton = SingletonMaker::getSingleton();
class MyFirstService
{
}
class MySecondService
{
}
class ServiceManager
{
private static $services = [];
public static function get(string $serviceClassName)
{
if (!isset(self::$services[$serviceClassName])) {
self::$services[$serviceClassName] = new $serviceClassName();
}
return self::$services[serviceClassName];
}
}
$myFirstService = ServiceManager::get('MyFirstService');
$mySecondService = ServiceManager::get('MySecondService');
class MyFirstService
{
}
class ServiceManager
{
private static $services = [];
public static function get(string $serviceName)
{
$serviceClassName = ucfirst($serviceName);
if (!isset(self::$services[$serviceName])) {
self::$services[$serviceName] = new $serviceClassName();
}
return self::$services[$serviceName];
}
}
$myService = ServiceManager::get('myFirstService');
🧙♂️️Ce que je comprends plutôt de ce qu'est le StaticFactory :
A la différence de l'AbstractFactory, on ne définit ici qu'une seule classe Factory ; étant donné qu'il n'y a qu'une seule classe Factory, il n'est donc pas nécessaire de mettre du code dans une classe abstraite (donc le fichier 'AbstractSomethingFactory.php' n'existerait pas). Le design pattern StaticFactory est un cas particulier de l'AbstractFactory.
index.php
<?php
$currentHour = (int) date('H');
if ($currentHour < 12) {
echo 'breakfeast';
} elseif ($currentHour < 16) {
echo 'lunch';
} else {
echo 'dinner';
}
<?php
function getMealName($currentHour): string
{
if ($currentHour < 12) {
$mealName = 'breakfeast';
} elseif ($currentHour < 16) {
$mealName = 'lunch';
} else {
$mealName = 'dinner';
}
return $mealName;
}
echo getMealName((int) date('H'));
function getMealTime($currentHour): string
{
if ($currentHour < 12) {
$mealTime = '0h - 12h';
} elseif ($currentHour < 16) {
$mealTime = '12h - 16h';
} else {
$mealTime = '> 16h';
}
return $mealTime;
}
echo getMealTime((int) date('H'));
MealInterface.php
<?php
namespace App\Model\Meal;
interface MealInterface
{
public function getName();
}
AbstractMeal.php
<?php
namespace App\Model\Meal;
abstract class AbstractMeal implements MealInterface
{
protected string $name;
public function getName(): string
{
return $this->name;
}
}
Breakfeast.php
<?php
namespace App\Model\Meal;
class Breakfast extends AbstractMeal implements MealInterface
{
public function __construct()
{
$this->name = 'breakfast';
}
}
Lunch.php
<?php
namespace App\Model\Meal;
class Lunch extends AbstractMeal implements MealInterface
{
public function __construct()
{
$this->name = 'lunch';
}
}
Dinner.php
<?php
namespace App\Model\Meal;
class Dinner extends AbstractMeal implements MealInterface
{
public function __construct()
{
$this->name = 'dinner';
}
}
MealController.php
<?php
namespace App\Meal\Controller;
use App\Meal\Model\Breakfast;
use App\Meal\Model\Lunch;
use App\Meal\Model\Dinner;
class MealController
{
public function index()
{
$currentHour = (int) date('H');
if ($currentHour < 12) {
$meal = new Breakfast();
} elseif ($currentHour < 16) {
$meal = new Lunch();
} else {
$meal = new Dinner();
}
echo $meal->getName();
}
}
MealFactory.php
<?php
namespace App\Meal\Factory;
use App\Meal\Model\MealInterface;
use App\Meal\Model\Breakfast;
use App\Meal\Model\Lunch;
use App\Meal\Model\Dinner;
class MealFactory implements MealFactoryInterface
{
public static function create(int $hour): MealInterface
{
if ($hour < 12) {
$meal = new Breakfast();
} elseif ($hour < 16) {
$meal = new Lunch();
} else {
$meal = new Dinner();
}
return $meal;
}
}
MealFactory.php
<?php
namespace App\Meal\Factory;
use App\Meal\Model\MealInterface;
interface MealFactoryInterface
{
public function create(int $hour): MealInterface;
}
MealController.php
<?php
namespace App\Meal\Controller;
use App\Meal\Factory\MealFactory;
class MealController
{
public function index()
{
$mealFactory = MealFactory::create((int) date('H'));
echo $meal->getName();
}
}
🧙♂️️L'usage des méthodes static est assez déconseillée car le Controller a ici une dépendance avec la classe concrète de la Factory. Si on souhaite utiliser une autre MealFactory, il faudra modifier dans l'ensemble du code cet usage. Mieux vaut que MealFactory implémente l'interface MealFactoryInterface. On injectera ensuite la Factory dans le constructeur des classes qui en dépendent.
📖️️https://designpatternsphp.readthedocs.io/en/latest/Creational/StaticFactory/README.html
📖️️https://waytolearnx.com/2020/02/design-patterns-static-factory-en-php.html