John Squibb

Using a Singleton to Manage Your Singletons. Wait, What?

I use the Singleton Design Pattern quite a bit, so much in fact, that I needed something to make using Singletons more seamless!

If you're not familiar with the Singleton Design Pattern, or how it pertains to PHP, then I suggest you check it out here.

If you are familiar with the pattern, and like me, have grown tired of adding getInstance() to all your classes and privatizing their constructors, then say hello to the Singleton class, known among his inner circle, as Mr. Singleton.

What's Wrong with the Standard Singleton Implementation?

Nothing whatsoever! But in order to convert your class to use the Singleton pattern, you have to do just that: convert all your classes. That's great if the only implementation you ever intend to use utilizes the getInstance() method. This may be exactly what you want for your database abstraction layer, or your helper classes that aren't static, or one of a gazillion other Singleton-worthy classes.

If you're just trying to cut some overhead by ensuring that your classes only get instantiated once per execution, then the Singleton contract might not be appropriate. Additionally, if you didn't have to refactor all your classes and bind them to the pattern, why would you?

Enter Mr. Singleton.

What Mr. Singleton Does for You

Basically, Mr. Singleton is just a final class that can't be constructed, that sits around waiting for you to request a class. When you do, he assumes the role of elephant, remembering every class you ask him for. If you ask him for it again, he gives you the original instance back, thereby preventing the overhead of additional instances.

Since Mr. Singleton creates the actual object, and remembers its state, all you have to do is ask him for the object, run the methods, and move along. You get all the benefits of the Singleton pattern without the disadvantages of refactoring your code. You can reduce overhead, and leave any preexisting or future code intact!

But enough of the cheesy code personification, let's have an example, shall we?

The Singleton Class

The code is pretty simple, just a few static methods and a member array to hold the instances.

<?php

final class Singleton
{
    
/**
     * Maintains collection of instantiated classes
     */
    
private static $instances = array();
    
    
/**
     * Overload constructor
     */
    
private function __construct(){}
    
    
/**
     * Manages instantiation of classes
     * 
     * @param $class
     * 
     * @return none
     */
    
public static function instance($class)
    {        
        
//instantiate class as necessary
        
self::create($class);    
        
        
//return instance
        
return self::$instances[$class];
    }
    
    
/**
     * Creates the instances
     * 
     * @param $class
     * 
     * @return none
     */
    
private static function create($class)
    {
        
//check if an instance of requested class exists
        
if (!array_key_exists($class self::$instances))
        {
            
self::$instances[$class] = new $class;
        }
    }
}

Toggle plain-text

Let's test Mr. Singleton with a sample class and some calls.

You can place the sample code in its own file and include Mr. Singleton, or you can just append it to the same file.

<?php
/**
 * Test Taco Class
 */
class Taco
{
    private 
$shell 'soft flour';
    
    public function 
__construct()
    {
        print 
"constructed\n";
    }
    
    public function 
shell()
    {
        return 
$this->shell "\n";
    }
    
    public function 
change_shell()
    {
        
$this->shell 'hard corn';
    }
}

// Ask Mr. Singleton for a taco.
$taco Singleton::instance('Taco');
print 
$taco->shell();

// We'd like to have another taco.
$taco2 Singleton::instance('Taco');

// Ah, it's the same taco!
print $taco2->shell();

// Change the taco a bit
$taco2->change_shell();
print 
$taco->shell();

// Can we we have another taco?
$taco3 Singleton::instance('Taco');

// Dang, it's the same taco.
print $taco3->shell();

Toggle plain-text

Summary

I utilize Mr. Singleton in a lot of my projects, and have grown quite fond of the ability to use him for quick one-off method calls without having to create a new instance of the class I am calling, even if I'm not concerned about redundant instances. Since Mr. Singleton's instance() method returns the instance of the requested object, as shown above in the samples, you can easily chain the first method call right to the back of your request!

Extend and Improve

As always, this could be extended. A lot of Singleton implementations tend to overload additional magic methods, especially __clone(). My goal here is less of a code-by-contract, and more of an ease-of-use approach. If preventing the clone of your objects is important to your project, then by all means, overload the __clone() method.

Suggested Reading

PHP 6 and MySQL 5

by Larry Ullman

I keep a copy of Visual Quickpro Guide, PHP 6 and MySQL 5 on my shelf to loan out to new PHP developers that have done little more than dabble in PHP for their personal website, and so on. I literally wore an older edition of this book out by reading it from cover-to-cover, re-reading it, and carrying it around with me everywhere I went. It was like my first guitar, I used the heck out of it! As the name implies, this book is designed to get you going. Larry Ullman does a great job of teaching the basics so that you can get a dynamyic website talking to a MySQL database, complete with forms, sessions, cookies, security mechanisms, and on and on...If you don't know PHP, but are looking for a great way to dive in, buy this book.

Suggested Reading

PHP Design Patterns

by Aaron Saray

Seasoned programmers looking for a good book on PHP design patterns will thoroughly enjoy PHP Design Patterns. Weighing in under 250 pages of readable content, it presents a truckload of philosophy and pattern samples in a well-condensed format, with short, consistent chapters. The title starts off with a quick explanation of patterns, champions their usage, and by chapter 3, the user is thrust right into the Adapter Pattern. For the next seventeen chapters, the user is given a synopsis, a problem/solution summary, a UML diagram, and code examples for each of the patterns in the discussed in the book. Generally, the code provides a typical approach, and then a modified approach using the chapter's pattern.

Tags: Singleton, Design, Pattern, seamless, getInstance, classes, PHP
Short URL: http://sqb.in/A2tI