Moving singleton and factory patterns to Abstract with php 5.3


I have built a backend library. I have a tree of classes and i want to use singleton and factory patterns to my class set. Easy isn’t it?

My dummy class

class Lib_Myclass
{
    public function function1($var1)
    {
        return $var1;
    }
}

new instance of my class

$obj = new Lib_Myclass;
$obj->function1('hi');

Ok. Nice OO tutorial Gonzalo, but I want to use factory pattern so:

class Lib_Myclass
{
    static function factory()
    {
        return new Lib_Myclass;
    }
    public function function1($var1)
    {
        return $var1;
    }
}

Lib_Myclass::factory()->function1('hi');

Now imagine you have a lot of classes. You must create over and over the factory function in every classes. OK you can create an abstract class and extend all classes with your abstract class but …

abstract class AbstractClass
{
    static function factory()
    {
        return new Lib_Myclass; // <---- what's the name of the class?
    }
}

Whats is the name of the class you will use when creating the new object? You can use __CLASS__ but it only works when you are in the parent class. In an extended class __CLASS__ points to the name of the abstract class and not the parent one. With php < 5.3 there are some tricks for doing it but those tricks are very ugly. In php 5.3 we have get_called_class. So now we can create an abstract class with or factory and singleton implementations and extend our classes without adding any extra code over and over again

abstract class AbstractClass
{
    static $_instance = null;

    static function singleton()
    {
        if (is_null(self::$_instance)) {
            self::$_instance = self::factory();
        }
        return self::$_instance;
    }

    static function factory()
    {
        $class = get_called_class();
        return new $class;
    }
}

And now or class:

class Lib_Myclass extends AbstractClass
{
    public function function1($var1)
    {
        return $var1;
    }
}

And use patterns:

<?php
Lib_Myclass::factory()->function1('hi');

Lib_Myclass::singleton()->function1('hi');

Clean and simple. I like it.

About these ads

About Gonzalo Ayuso

Web Architect specialized in Open Source technologies. PHP, Python, JQuery, Dojo, PostgreSQL, CouchDB and node.js but always learning.

Posted on December 7, 2009, in php, Web Development. Bookmark the permalink. 2 Comments.

  1. Hey, I’ve played around with this as well, but what you have won’t quite work. You can’t name your class “Abstract” because it is a reserved word. Also you can’t do “new get_called_class()” because PHP will look for a class called “get_called_class”. Instead you need to store the result of get_called_class() in a variable and then do “new $variable;”. It is a fun concept though.

    • Updated. I tried to reduce the code to the example and as you said the example didn’t work. Thanks.
      The main problem I have with that idea is phpdoc. I cannot do the same trick in phpdoc and I cannot comment properly the factory function (I don’t know the real class and I cannot use get_called_class here) so my IDE won’t help me when I code Lib_Myclass::factory()->. I need to use a variable: $a = Lib_Myclass::factory(); and use PHPDoc with the variable $a.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 973 other followers

%d bloggers like this: