Example 1

Use case: We want to hide the creational logic in our code from this Adapter pattern example because we don't want to repeat this step every time we want to create a payment method. It also makes it easy for us if want to modify the implementation we need to do this in one place only even though we use the payment method in various places in our app.

<?php

interface PaymentFactoryInterface
{
    // Read the Adapter pattern example in use case
    // to understand where the PaymentInterface comes form

    public static function create(string $type) : PaymentInterface; 

    public static function createPaypalPayment(): PaymentInterface;

    public static function createStripePayment(): PaymentInterface;
}

And the implementation

<?php

class PaymentFactory implements PaymentFactoryInterface
{
    public static function create(string $type): PaymentInterface
    {
        $methodName = 'create'. ucfirst($type) . 'Payment';
        if ( !method_exists(self::class, $methodName) ) {
            throw new \Exception("No Payment $type found");
        }

        return self::$methodName();
    }

    public static function createPaypalPayment(): PaymentInterface
    {
        $paypal = new Paypal();
        return new PaypalAdapter($paypal);
    }

    public static function createStripePayment(): PaymentInterface
    {
        $stripe = new Stripe();
        return new StripeAdapter($stripe);
    }
}

 Compare the client code without the factory

 

<?php

// No factory
$paypal = new \App\Structural\Adapter\ExampleOne\Paypal();
$payment = new PaypalAdapter($paypal);


// With factory
$payment = PaymentFactory::create('paypal');
// Or be explicit 
$payment = PaymentFactory::createPaypalPayment();
$payment->pay(20)