Factory
El diseño orientado a objetos enfatiza la clase abstracta por encima de la implementación. Es decir, trabaja con generalizaciones más que con especializaciones. El patrón del “Método de Fábrica” aborda el problema de cómo crear instancias de objetos cuando su código se centra en tipos abstractos. Dejando que las clases especializadas se encarguen de la instanciación.
Una superclase especifica todo el comportamiento estándar y genérico (usando puros “marcadores de posición” virtuales para los pasos de creación), y luego delega los detalles de la creación a subclases que son suministradas por el cliente.
Ejemplo:
<?php
class Animal {
private $name;
private $type;
public function __construct(string $name, string $type) {
$this->name = $name;
$this->type = $type;
}
public function getNameAndType(): string {
return $this->name . " " . $this->type;
}
}
class AnimalFactory {
public static function create(string $name, string $type) {
return new Animal($name, $type);
}
}
$cat = AnimalFactory::create("Cat", "Mammal");
echo $cat->getNameAndType();
echo "<br>";
$snake = AnimalFactory::create("Snake", "Reptile");
echo $snake->getNameAndType();
Prototype
El patrón de diseño de Prototipo es interesante en su uso de una técnica de clonación para replicar objetos instanciados. Los nuevos objetos se crean copiando instancias prototípicas. En este contexto, los casos se refieren a clases concretas instanciadas. El objetivo es reducir el costo de la instanciación de objetos mediante la clonación. En lugar de instanciar nuevos objetos de una clase, se puede utilizar un clon de una instancia existente.
El patrón Prototipo también se ha utilizado para crear una estructura organizacional en la que se puede crear y ocupar un número finito de puestos en función de la organización real. Se han utilizado prototipos en los que se ha creado un objeto de dibujo utilizando la composición y luego se ha clonado para diferentes versiones.
Ejemplo:
<?php
abstract class FoodPrototype {
protected $name;
protected $type;
abstract function __clone();
function getName(): string {
return $this->name;
}
function setName(string $name) {
$this->name = $name;
}
function getType(): string {
return $this->type;
}
}
class VegetablePrototype extends FoodPrototype {
function __construct() {
$this->type = "vegetable";
}
function __clone() {}
}
class FruitPrototype extends FoodPrototype {
function __construct() {
$this->type = "fruit";
}
function __clone() {}
}
$vegetableProto = new VegetablePrototype();
$fruitProto = new FruitPrototype();
$vegetable1 = clone $vegetableProto;
$vegetable1->setName('Carrot');
echo "Food name: " . $vegetable1->getName() . "<br>";
echo "Food type: " . $vegetable1->getType() . "<br>";
echo "<br>";
$fruit1 = clone $fruitProto;
$fruit1->setName('Banana');
echo "Food name: " . $fruit1->getName() . "<br>";
echo "Food type: " . $fruit1->getType() . "<br>";
echo "<br>";
$vegetable2 = clone $vegetableProto;
$vegetable2->setName('Tomato');
echo "Food name: " . $vegetable2->getName() . "<br>";
echo "Food type: " . $vegetable2->getType() . "<br>";
echo "<br>";
Resultado:
Food name: Carrot
Food type: vegetable
Food name: Banana
Food type: fruit
Food name: Tomato
Food type: vegetable
Singleton
El patrón Singleton asegura que una clase tiene sólo una instancia y proporciona un punto de acceso global a esa instancia. Recibe su nombre por el conjunto de un solo elemento, que se define como un conjunto que contiene un elemento.
El uso del patrón Singleton está justificado en aquellos casos en los que queremos restringir el número de instancias que creamos a partir de una clase para ahorrar recursos del sistema. Estos casos incluyen conexiones a bases de datos, así como APIs externas que consumen los recursos del sistema.
Ejemplo:
<?php
class FoodBowl {
private $bowl = [];
private static $instance;
private function __construct() {}
public static function getInstance() {
if (empty(self::$instance)) {
self::$instance = new FoodBowl();
}
return self::$instance;
}
public function addIngredient(string $ingredient) {
$this->bowl[] = $ingredient;
}
public function getIngredients(): array {
return $this->bowl;
}
}
$bowl1 = FoodBowl::getInstance();
$bowl1->addIngredient("carrots");
unset($bowl1);
$bowl2 = FoodBowl::getInstance();
print_r($bowl2->getIngredients());
En el ejemplo se demuestra como al eliminar $bowl1
se sigue manteniendo la instancia y se puede accesar a la información desde $bowl2
.