Prototype Pattern in PHP

Next up is the final creational pattern I’m going to cover in this series.

It’s the prototype pattern…. it’s literally beyond simple, so let’s get going.

What is the prototype pattern

The concept behind the prototype pattern is to create objects by cloning existing objects instead of initialising new objects. I haven’t actually benchmarked this myself in PHP to see the benefit, however cloning is for sure less processor intensive – I’ll get onto why in a bit. That isn’t to say objects should always be cloned. Unless you’re creating hundreds or more objects of the same class, you’re probably not going to notice any difference.

Cloning objects in PHP is extremely easy due to its magic __clone() method and the clone keyword.

Rules

  1. Make sure the class of the object being class being cloned has a public __clone() magic method. It doesn’t matter if their is no content to the method.

Advantages

  1. The time taken to clone an object is quicker than it would be to initialise a new object. This is because when an object is cloned the constructor is not re-executed.

Drawbacks

  1. When an object is cloned the constructor is not re-executed. Constructors should not deal with any business logic other than maybe setting some variables. So this shouldn’t be a problem anyway, but if you’re working on a legacy code base, this is worth taking into consideration.

Example

/**
 * A class to represent the CocaCola drink
 */
class CocaCola {
    
    private $fizzy;
    private $healthy;
    private $tasty;

    /**
     * init a CocaCola drink
     */
    public function __construct() {
        $this->fizzy   = true;
        $this->healthy = false;
        $this->tasty   = true;
    }

    /**
     * This magic method is required, even if empty as part of the prototype pattern
     */
    public function __clone() {
    }

}

$cola = new CocaCola();

/*
 * object(CocaCola)#1 (3) {
 *   ["fizzy":"CocaCola":private]=>
 *   bool(true)
 *   ["healthy":"CocaCola":private]=>
 *   bool(false)
 *   ["tasty":"CocaCola":private]=>
 *   bool(true)
 * }
 */
var_dump($cola);

$colaClone = clone $cola;

/*
 * object(CocaCola)#2 (3) {
 *   ["fizzy":"CocaCola":private]=>
 *   bool(true)
 *   ["healthy":"CocaCola":private]=>
 *   bool(false)
 *   ["tasty":"CocaCola":private]=>
 *   bool(true)
 * }
 */
var_dump($colaClone);

Conclusion

Thats it. Pretty simple ayyy! This admittedly isn’t the best use case, but I didn’t want to complicate something, which is so simple. The prototype pattern really comes into it’s own, when the constructor starts doing any kind of work and by using cloning, you only have to make one call to the constructor. Constructors should never do anything but set values anyway, but if setting these values means calling complex expressions. This is something you would be better off only doing once, instead of thousands of time or more.

13 Love This

Leave a Reply

Your email address will not be published.