When you think of a factory, what comes to mind? For me, it's a place where things are created - that is, it's a centralized placed where things are produced. Later, the delivery of said products are done by the factory based on an order.
Let's say that you're requesting a car - a factory will create one based on the specifications of the work order and will then deliver it once it's complete.
Just as their real world counterparts, software factories (that is, software that implements the factory design pattern), is an object that's responsible for creating and delivering other objects based on incoming parameters.
There are three variations of the factory pattern:
- Simple Factory Pattern. This allows interfacing to create objects without exposing the object creation logic to the node.
- Factory Method Pattern. This allows interfacing to create objects, but allow subclasses to determine which class to instantiate.
- Abstract Factory Pattern. Unlike above two patterns, Abstract Factory is an interface to create of related objects, without specifying/exposing their classes. Or we can say that it provides object of another factory which is responsible to create required objects.
The Problem
Let's assume that you have a car class that contains all properties and methods relevant to a automobile. In it's most basic form, you'd create it like this:
$car = new Car();
Immediately, as time goes there needs to be some change in how the Car object is being created. We need to create class obejcts based on Cart Type instead of just Car. So you need to make changes in all the places where you have created object of this Car class.
But, as time goes by, there will inevitably need to be changes in how the Car object is created. For example, we need to create classes based on a "Car" type rather than just "Car." As such
Instead of going into such situation, it would be a safe decision to make an object of such classes with the use of Factory compared to new keyword.
As per Factory, new keyword is considered as harmful.
The Solution
In the previous section we have realized that we were creating an Object of Car using the new method. And later it is decided to create an object of Car class, but based on Car type like Sedan, SUV, etc.
Hence either we should place Car type class creation code at all places whenever required or implement Factory to handle it in an effective manner. Please refer below code block which shows the implementation of the Simple Factory Pattern.
class carFactory { public function __construct() { // ... // } public static function build ($type = '') { if($type == '') { throw new Exception('Invalid Car Type.'); } else { $className = 'car_'.ucfirst($type); // Assuming Class files are already loaded using autoload concept if(class_exists($className)) { return new $className(); } else { throw new Exception('Car type not found.'); } } } }
In the above class, You can see that we have one static method is available which is responsible to create Object based on the type you pass. Now what we needed is concrete classes of different car types which are as listed below:
class car_Sedan { public function __construct() { echo "Creating Sedan"; } } class car_Suv { public function __construct() { echo "Creating SUV"; } }
Up to here, we have our Factory and Concrete classes are ready to use, so let's practice it for creating require car type objects.
// Creating new Sedan $sedan = carFactory::build('sedan'); // Creating new SUV $suv = carFactory::build('suv');
Addition of New Class
Addition of new class is as uncomplicated as it is. Just create one concrete class and you are ready to go, below code says all things:
class car_Luxury { public function __construct() { echo "Creating Luxury"; } } // Creating new Luxury $luxury = carFactory::build('luxury');
Conclusion
Equally I have referred earlier, use of new keyword to create a new object is harmful and we should be implementing factory pattern to have our object creation code centralized.