
In this tutorial we will demonstrate The Factory Method Pattern. This is another creational pattern which aims to creating objects from another classes without revealing the actual class implementation and also achieves the “Dependency Inversion Principle”.
the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created.
so to create an object instead of using the class constructor there will be a another class that will handle creating objects of those classes. This is done by creating a factory method in the creator class which will take for example the class name and returns a new instance from it.
let’s see this in action:
in this example we will create an interface that represents the geometric shapes.
<?php interface Shape{ public function draw(); } class Position{ public $x; public $y; } class Rectangle implements Shape{ private $position; public function __construct(Position $pos) { $this->position = $pos; } public function draw(){ echo "Drawing a rectangle with position (".$this->position->x .",".$this->position->y.")<br/>"; } }
In the code above we created a class called Rectangle that extends from the Shape interface. Each shape has a position so we injected the Position class through a dependancy injection in the constructor.
Imagine we want to create instance of this class we can use the classic way with new:
<?php $pos = new Position; $pos->x = 34; $pos->y = 55; $rectangle = new Rectangle($pos); var_dump($rectangle); $rectangle->draw();
It will work but Imagine we have a class for each different shape like circles, triangles, squares. Creating new instance in this way forces you to remember the class name and also has disadvantages of tight coupling.
What about creating a factory class:
<?php class ShapeFactory{ public function create($class, $position) { return new $class($position); } }
here we created a factory object that takes the class name and position
<?php /** * will output the same result as the example above * but this time using the factory method */ echo "<pre>"; $pos = new Position; $pos->x = 34; $pos->y = 55; $shape = new ShapeFactory; $rect = $shape->create("Rectangle", $pos); var_dump($rect); $rect->draw();
let’s create another shape class:
<?php class Circle implements Shape{ private $position; public function __construct(Position $pos) { $this->position = $pos; } public function draw(){ echo "Drawing a circle with position (".$this->position->x .",".$this->position->y.")<br/>"; } } class Triangle implements Shape{ private $position; public function __construct(Position $pos) { $this->position = $pos; } public function draw(){ echo "Drawing a triangle with position (".$this->position->x .",".$this->position->y.")<br/>"; } } echo "<pre>"; $pos->x = 100; $pos->y = 20; $circle = $shape->create("Circle", $pos); var_dump($circle); $circle->draw(); $pos->x = 110; $pos->y = 50; $triangle = $shape->create("Triangle", $pos); var_dump($triangle); $triangle->draw(); echo "</pre>";
This is another example suppose we have a class for each Car so we will create a CarFactory
<?php /* Car interface */ interface Car { public function getType(); } /* Concrete implementations of the Car interface */ class Sedan implements Car { public function getType() { return 'Sedan'; } } class Kia implements Car { public function getType() { return 'Kia'; } } class BMW implements Car { public function getType() { return 'BMW'; } } /* Car factory interface responsible for creating car */ interface CarFactory { public function createCar(); } /* Concrete implementations of the factory */ class SedanFactory implements CarFactory { public function createCar() { return new Sedan(); } } class KiaFactory implements CarFactory { public function createCar() { return new Kia(); } } class BMWFactory implements CarFactory { public function createCar() { return new BMW(); } } /* Client code */ $factory = new KiaFactory(); $car = $factory->createCar(); // will create a new instance print $car->getType();
In the example above represents another way of dealing with the factory pattern as it creates two interfaces one represents the Car type and one represents the Car Factory and we created different concrete implementations of each interface then the client code will call the Factory class instead of the original Car class.