The Singleton

One of the first PHP design patterns that sticks in your mind when learning about design patterns is the Singleton pattern. Why? Because the Singleton has a catchy name and is easy to remember. The purpose of a singleton is to have only one instance of an object available to you every where in your system, one and only one instance. I hear that, and I think of Sean Connery in the movie, "The Hunt for Red October," when he said, "Give me a ping, Vasily. One ping only."

It sounds simple, but implementing it is tricky, and getting it working properly, even trickier. If you look up how to construct a singleton on the Internet, you'll find different confusing solutions, all examples, none are implemented. We'll use an actual example of a working singleton in this article.

Why use a singleton? The Singleton takes the place of a global Variable. We all know that it's a no-no to use global variables, Global variables tightly couple the variable into the entire system, and are easy to change anywhere in the system, and that change could result in an error in another part of your system that will show up in strange ways with wrong results. There is no system error thrown when the data is garbage. That type of error can be difficult to find and fix.

As with the global variable, the singleton is tightly coupled to your system, singletons are hard to encapsulate and use with other systems, which is why you see so many diverse solutions to the singleton pattern. However, used sparingly, they are ideal for what they bring to the party.

The singleton, unlike a global variable, protects its data from changing unless you use the class interface. This makes the chance of another programmer accidentally changing your variable a lot less likely, its protected. At the same time, when you need that variable, you'll know its the same value you set 2000 lines of code ago, because it the same object, remember one and only one.

My real world example, I am working on a web accounting application that spans several years, however, every year is unique for accounting purposes. The system has many pages of tables and forms for different accounting functions. With each page, you want to use data from the correct year. Thus "the year" is used through out the system.

I started developing the system by passing the year across the pages with a session variable. The "year" session variable spread across the entire system, and I started having problems as users wanted to change years in one part of the system and have it promulgate through out the entire system. As the system grew, it started to become a nightmare keeping track of which version of the "year" I was using. Time to refactor, and time for a Singleton.

There are three goals to keep in mind when constructing the singleton: protect the data, make sure that only one instance of the object can be created, and make the object universally available throughout the system. Let's put together a class to accomplish those goals.

class TheYear 
{
// Protect the data
private $currentYear ;

// Protect the instance
private static $YearObject ;

// Our constructor
private function __construct() { }

// To prevent cloning or copying of the object
private function __clone() {}

// One instance, one instance only
public static function getYearObject()
{
	if( empty(self::$YearObject()) )
	{
        self::$YearObject = new TheYear();
    }
    return self::$YearObject;
}

// To return the current year
public function getTheYear() 
{
	return $this->currentYear;
}

// To set and change the current year
public function setCurrenYear($acctYear)
{
   $this->currentYear = $acctYear;
}
}

How does this class achieve our goals? First, we want to protect our data. We did that by making the $currentYear private and only accessible through a class methods.

Next, we want to make sure only one object is generated. We do this in five ways, first, by making that object, once created, a property, like the $currentYear, and labeling it as private.

Second, we cut off any cloning or copying of the object with the private empty clone method.

Third, we make the constructor of our object private, which means we'll be forced to use an internal class method to instantiate the object. You will not be able to generate a new instance of the object with a "new" keyword.

Fourth, we generate our object with a getYearObject() method. We first check to see if the object was already created, if not, we create a new object and store it in $YearObject property, thus only one object fills the $YearObject property, and it is the same instance for all accesses.

And last, we'll use the static key word on the getYearObject() method that sets the static $YearObject property from any where in our system, and prevents an object from accessing either the method or property.

To access our $currentYear variable we'll use the $YearObject. Since throughout the system its the same object, we always return the same result for $currentYear. This allows us to treat $currentYear like a regular class property with its own methods. I know its round about, but it achieves our goals.

We, now, can call the getYearObject method from anywhere in the system, which will return our static object, and then use the object to get our $currentYear with a class method. We use the :: operator and the "self" keyword to access the static elements, not the -> and "$this" keyword we use with objects.

We finish our class with standard class methods, a set method to change the year, and a get method to get the $currentYear to use in our system.

I said the singleton was tricky to implement, and we haven't gotten to how to use it yet, which is a little trickier, because of that, we're not quite done with our class yet. We'll cover that in our next article.

Comments are closed.