What Is a Factory Design Pattern in PHP

What is a Factory Design Pattern in PHP?

A factory creates an object. So, if you wanted to build

 class A{
public $classb;
public $classc;
public function __construct($classb, $classc)
{
$this->classb = $classb;
$this->classc = $classc;
}
}

You wouldn't want to rely on having to do the following code everytime you create the object

$obj = new ClassA(new ClassB, new Class C);

That is where the factory would come in. We define a factory to take care of that for us:

class Factory{
public function build()
{
$classc = $this->buildC();
$classb = $this->buildB();
return $this->buildA($classb, $classc);

}

public function buildA($classb, $classc)
{
return new ClassA($classb, $classc);
}

public function buildB()
{
return new ClassB;
}

public function buildC()
{
return new ClassC;
}
}

Now all we have to do is

$factory = new Factory;
$obj = $factory->build();

The real advantage is when you want to change the class. Lets say we wanted to pass in a different ClassC:

class Factory_New extends Factory{
public function buildC(){
return new ClassD;
}
}

or a new ClassB:

class Factory_New2 extends Factory{
public function buildB(){
return new ClassE;
}
}

Now we can use inheritance to easily modify how the class is created, to put in a different set of classes.

A good example might be this user class:

class User{
public $data;
public function __construct($data)
{
$this->data = $data;
}
}

In this class $data is the class we use to store our data. Now for this class, lets say we use a Session to store our data. The factory would look like this:

class Factory{
public function build()
{
$data = $this->buildData();
return $this->buildUser($data);
}

public function buildData()
{
return SessionObject();
}

public function buildUser($data)
{
return User($data);
}
}

Now, lets say instead we want to store all of our data in the database, it is really simple to change it:

class Factory_New extends Factory{
public function buildData()
{
return DatabaseObject();
}
}

Factories are a design pattern we use to control how we put objects together, and using correct factory patterns allows us to create the customized objects we need.

Factory Method Design Pattern -PHP

Simple Factory

A simple class with different methods (or one with a switch) that is fully implemented with the creation logic. In PHP it can look like:

class AnimalFactory
{
public function CreateAnimal($type)
{
if ($type == 'Dog') {
return new Dog();
} else {
return new Cat();
}
}
}

If tommorow you'll have a new animal to support, you will have to change this class implementation.
There are no subclasses here - this class knows everything about Animal creation.

Factory Method

Is what you use when you have a class that does some proccessing with Animal but doesn't know how or which Animal to create yet, therfore would like to have subclasses that will determine that. So we create a factory method that the sucblasses can override.

abstract Class MyAnimalProcess
{
abstract function CreateAnimal();

public function Process()
{
$animal = $this->CreateAnimal();
...
...
}
}

class DogProcess extends MyAnimalProcess
{
function CreateAnimal()
{
return new Dog();
}
}

So, here you can have and abstract class that does something with an Animal, but let the subclasses of it determine which Animal it will be.

Abstract Factory

Take the factory method one step forward, and delegates the creation to another class - "the factory" class.

So it uses composition rather than inheritance.

abstract class AnimalFactory
{
public abstract function CreatePet();
public abstract function CreateWildAnimal();
}

class DogAnimalFactory extends AnimalFactory
{
public function CreatePet()
{
return new Dog();
}

public function CreateWildAnimal()
{
return new AfricanWildDog();
}
}

class CatAnimalFactory extends AnimalFactory
{
public function CreatePet()
{
return new Cat();
}

public function CreateWildAnimal()
{
return new Tiger();
}
}

class MyAnimalProcess
{
function __construct($animalFactory) {
$this->factory = $animalFactory;
}

public function ProcessPet()
{
$animal = $this->factory->CreatePet();
...
...
}

public function ProcessWild()
{
$animal = $this->factory->CreateWild();
...
...
}
}

what is factory in php and how it can be useful?

An AbstractFactory is a Creational Design Pattern, that

Provides an interface for creating families of related or dependent objects without specifying their concrete classes.

In a nutshell:

class MercedesFactory
{
public static function createCar()
{
$engine = new MercedesEngine;
$car = new Mercedes($engine);
return $car;
}
}
  • AbstractFactory Example in PHP Code 1
  • AbstractFactory Example in PHP Code 2

There is also the Factory Method, which

Defines an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

In a nutshell:

class User
{
public static function create()
{
return new self;
}
}
  • Factory Method Example in PHP Code

How to implement factory design pattern

The idea of the factory pattern is to decouple and encapsulate the logic required to create an instance of an object, from the object itself. This separates concerns.

You currently have a static method on your User class that is responsible for fetching the user information from the database. This couples your User object to your database. It's also very rigid.

  • What if your users are stored in a different type of database?
  • What if your users are stored in an XML file?
  • What if your users are stored in a key/value store?
  • What if you want to create a mock repository of users for writing tests?

The factory pattern allows you to abstract these concerns away, and provide alternate implementations of a factory depending on your needs (assuming you had a common interface for each implementation). Maybe the way you create a user changes, but you don't want to also change everywhere you've needed to create a user - just how the user is created. Isolating this code into a factory allows for this.

A factory might take an instance to your DAL as well, if you've abstracted your DAL. (I'll be using IDataAccessLayer as a placeholder for your preferred DAL)

class UserFactory {
private IDataAccessLayer $dataAccessLayer;

public function __constructor($dataAccessLayer) {
$this->dataAccessLayer = $dataAccessLayer;
}

public function createUser($userId) {
$userDataSet = $this->dataAccessLayer->someQuery($userId);

switch ($userDataSet->type) {
case UserType::Administrator:
return createAdministrator($userDataSet);
case UserType::Moderator:
return createModerator($userDataSet);
case UserType::Ordinary:
return createOrdinaryUser($userDataSet);
}
}

private function createAdministrator($userDataSet) { /* Create and return an administrator */ }
private function createModerator($userDataSet) { /* Create and return a moderator */ }
private function createOrdinaryUser($userDataSet) { /* Create and return an ordinary user */ }
}

You'd then use this like:

$factory = new UserFactory($dataAccessLayer);
$factory->createUser(1);

(Bear with me, I haven't coded PHP in some years, so some of my syntax may be off, but the idea is the same)

Now, personally, it looks like you need to get even more granular here. I'd create a UserRepository following the Repository pattern. This is because the factory shouldn't really be accessing the database in my opinion. It should just use the data from the database to create the user. The repository pattern should be responsible for getting the data from the database, and then feeding that data to the factory pattern to get an object.

class UserRepository {
private IDataAccessLayer $dataAccessLayer;

public function __constructor($dataAccessLayer) {
$this->dataAccessLayer = $dataAccessLayer;
}

public function getUserById($id) {
$userData = $this->dataAccessLayer->fetch(someQuery);

$factory = new UserFactory();
return $factory->createUser($userData);
}
}

Then you'd have a simpler factory:

class UserFactory {
public function createUser($userData) {
switch ($userData->type) {
case UserType::Administrator:
return createAdministrator($userData);
case UserType::Moderator:
return createModerator($userData);
case UserType::Ordinary:
return createOrdinaryUser($userData);
}
}

private function createAdministrator($userDataSet) { /* Create and return an administrator */ }
private function createModerator($userDataSet) { /* Create and return a moderator */ }
private function createOrdinaryUser($userDataSet) { /* Create and return an ordinary user */ }
}

And from your code, you'd have something like:

$userRepository = new UserRepository($dataAccessLayer); //This is probably done somewhere higher in your code.
$userRepository->getUserById(1);

You'll probably want to go ahead and create the following interfaces and implement these as well. This will allow you to enforce your contract, as well as set yourself up to be able to swap out implementations if you need.

public interface IUserRepository {
function getUserById($userId);
}

and

public interface IUserFactory {
function createUser($userData);
}

Factory Design Pattern in PHP, Is this correct?

Yes, that's implements the Factory Design Pattern, but, it's much better to use a static method, as follows:

public static function getInstance($type) { ... }

To get an instance:

$db = DBFactory::getInstance(DBFactory::MYSQL);

Using the Factory Pattern in PHP and Laravel

Well, actually the Factory Pattern is a creational pattern which uses factory methods to deal with the problem of creating objects even without specifying a staic class, which means it create objects dynamically at the run-time. This pattern is used to deal with object creation mechanisms which lets a client class to to use a dynamic class built on run time. This pattern uses a factory method (abstract) and this method builds objects using other classes/objects depending on the request of the client class that uses the built object. Well, it's a broad thing, anyways.

Instead of thinking in design-patterns such as which pattern you should follow, try to find out the use case of your class and use them accordingly. Most probably you meant Model as classes which extends Eloquent ORM and in this case your model classes already have those methods if you extended the Eloquent ORM so you don't need to create those in your classes but to separate the business logic and DB layer you may use normal classes where you may use those classes as dependencies to call methods from your database layer classes. probably it sounds confusing anyways.

It depends on you how do you organize your directory structure but only think about SoC and that's enough to get the idea, for a clean application architectural pattern. Don't think too deep in design patterns, instead think of a clean application model, that's it. Probably this article may help you a little bit (Specially discussed using Laravel and Repository Pattern).

For Factory Pattern, you may check this simple but helpful article.

Factory / Abstract Factory confusion

The difference between Factory and Abstract Factory is pretty simple. In the latter, the factory itself is abstract (!) and cannot be instantiated directly, but must be sub-classed.

Per example, Factory:

class Document {
public function createPage() {
return new Page;
}
}

class LandscapeDocument extends Document {
public function createPage() {
return new LandscapePage;
}
}

In Abstract Factory:

abstract class Document {
abstract public function createPage();
}

class PortraitDocument extends Document {
public function createPage() {
return new PortraitPage;
}
}

class LandscapeDocument extends Document {
public function createPage() {
return new LandscapePage;
}
}

In short, the Factory pattern has a default implementation in the factory class itself. The Abstract Factory requires all sub-classes to implement their own version of the factory methods.

That's all there is to it.

PHP Abstract Factory Pattern Implementation

I think You've made a major mistake. Abstract factory purpose it to create an abstraction for creation of family of products, so you can easily change it to different family.
f.e. Apple => Samsung :)

interface ComputerAbstractFactory {
/**
* @return Tablet
*/
function createTablet();
/**
* @return Phone
*/
function createPhone();
/**
* @return Computer
*/
function createComputer();
}

class AppleComputerFactory implements ComputerAbstractFactory {}

class SamsungComputerFactory implements ComputerAbstractFactory {}

class IPad implements Tablet {}

class GalaxyTab implements Tablet {}

...

Using abstract factory pattern makes sense when You want to switch between both companies.
Your code should depend only on abstractions (SOLID principles) ComputerAbstractFactory, Tablet, Phone, Computer.
This way if you decide (f.e. by some configuration switch) which manufacturer should be used it's enought that you inject choosen implementation of ComputerAbstractFactory into your bussiness
code and you are done - everything works, tablets get created, phones etc

You need to decide what abstraction you want to create in your application so the calling code will not be coupled to concrete implementations of that abstraction. I believe that IPlayer is what you want, where IPodClassic IPodShuffle are concrete implementations.
If i'm right you should create IPlayerFactory

class IPlayerFactory {
/**
* @return IPlayer
*/
function create() {...}
}

About the duplication you mentioned. If iPodFactory extends AbstractAppleFactory it should implement all it's method (btw if AbstractAppleFactory does not have any implementation it should be an interface)
You broke Liskov principle from SOLID principles. Short version - if the calling code depends on AbstractAppleFactory and it gets iPodFactory as concrete implementation to operate on, it will break on calling createiPhone or createComputer - so abstraction does not work in that case.



Related Topics



Leave a reply



Submit