1. The problem

Let’s take an example, you designed your program to handle a payment flow on an e-commerce platform. You wrote a class, ShopifyPayment – for example, all of your logic code start from here and things ran smoothly, seem nothing could make you confused.

But one day, your boss said that they have made a contract with Wix, now you have to integrate your company’s payment product with not only Shopify platform, but also Wix, and maybe many other ones in the future.

So what will you and the team gonna do? Actually, there are many solutions for those kinds of problems, in this article, we will handle it in a very simple way: using the `Abstract Factory` pattern.

2. The solution

First, you will create a class the determine your payment method is applying for which platform, then process the corresponding class

The idea is, you may create a bunch of Platform classes that process the payment, and the main operator will determine which platform will be used by the Factory. Of course, this leads to one thing is that your logic code will be hidden.

In fact, many systems start by using Factory, It is very easy to implement and customize

3. The rule

The rule of the factory pattern is quite simple, in the case above, you have to make sure that

  • Every PlatformPayment follow the same interface and have “make sense” methods. In the image above, they all have checkout() method
  • The return type of those method have to follow the inteface

4. The Implementation

Let take a look at the example below:

<?php

class Payment 
{
    public function pay()
    {
        $platform = new ShopifyPayment();
        return $platform->checkout();
    }
}

class ShopifyPayment 
{
    public function checkout()
    {
        // your payment method processed
        return "Paid on Shopify";
    }
}

Very amateur! Ok, let make it better

class Payment 
{
    protected $platformName;

    public function __construct($platformName)
    {
        $this->platformName = $platformName;
    }
    
    public function pay()
    {
        $platformFactory = new PlatformFactory();
        $platform =  $platformFactory->create($this->platformName);
        return $platform->checkout();
    }
}

class PlatformFactory 
{
    public function create($platformName)
    {
        if ($platformName == 'shopify') {
            return new ShopifyPayment();
        } else if ($platformName == 'wix') {
            return new WixPayment();
        } else {
            throw new Exception("Platform does not exist"); 
        }
    }
}

class ShopifyPayment 
{
    public function checkout()
    {
        // your payment method processed
        return "Paid on Shopify";
    }
}

class WixPayment 
{
    public function checkout()
    {
        // your payment method processed
        return "Paid on Wix";
    }
}

$payment = new Payment('wix');
echo $payment->pay();

Here the result

Check if ‘platform’ was not supported:

$payment = new Payment('magento');
echo $payment->pay();

The thing go right!

We also make a small change so our code looks more professional:

class Payment 
{
    protected $factory;
    protected $platformName;

    public function __construct($factory, $platformName)
    {
        $this->factory = $factory;
        $this->platformName = $platformName;
    }
    
    public function pay()
    {
        $platform =  $this->factory->create($this->platformName);
        return $platform->checkout();
    }
}

$payment = new Payment(new PlatformFactory(), 'wix');
echo $payment->pay();

The Payment class now will not fully depend on only one Factory!

5. The conclusion

The Factory pattern, in the real world, is a bit more complicated, but in general, we could understand it by the sample above!

Posted in PHP

One thought on “Factory pattern in PHP – make the complicated logic disappear!

Leave a Reply

Your email address will not be published. Required fields are marked *