Most of us programmers, are very attached to our code, and find beauty not just in the end result (the working application), but also in the architecture and the actual code. As I am sure you’ve heared many times before, “Code is poetry”. And nowhere else is this concept more palpable then in Object-Oriented Programming.
The fact the Object-Oriented Programming is a major concept in programming today is unanimously accepted. From the basic OOP principles like Data abstraction, Inheritance etc., a programmer will end up learning and, most important, using what we call Design Patterns. Everyone heard about them, most us used them and the others learn them.
Now, why exactly are they so important and, dare I say, cool? If you think that getting an application to work the way it should is enough, then this series is the thing for you. First, I’d like to make a very brief introduction for describing Design Patterns. What are they? Let’s start by making an analogy with Programming Methods, like Backtracking, Dynamic programming, Greedy etc. What do they have in common? Obviously, they are aimed at solving a particular type of problem. For example, Backtracking finds all the solutions to a problem, Dynamic programming is used when the main problem can be solved by combining the results from overlapping subproblems. With this in mind, it is important to point out that Designed patters are used for designing code for a specific problem in an application.
First thing to understand when learning design patters, is the way they are classified:
Each of these three categories has a whole list of patterns aimed at increasing code flexibility, by meeting a certain need.
Starting with the first category and according to The great book, there are five patterns, each designed for a specific task:
Anyone wanting to learn them should consider the question regarding which pattern to start with. I must say that I’m in no position to suggest a certain order, they are all important, but it so happens that I first encountered the Singleton pattern, so I’ll start here.
The Singleton pattern – what it’s good for
It’s hard to explain an algorithm or a concept without relating to a specific language. So in this sense, I’ll describe this pattern using PHP, with a relevant example. Like I said earlier, this pattern is used when only one instance of an object must be made available throughout an application, and support a global access route to that instance. Let’s think about that for a second and ask how that can be achieved. Well, first of all it means that me must have a global instance which sould be avaiable at any time, but most importantly, making sure that new objects of that certain type cannot be created. Since objects are created using the new operator, we need to make sure that a new object can’t be instanciated that way. This can be done using a protected contructor for the Singleton class. That way, only the class is responsible for creating new objects, let’s say, using public methods, which call the constructor. Now that we have the constructor, it’s time to think about the instance, because that alone won’t meet the requirement. The logical way to do this, is to make the class handle the instance also, by defining a private variable, which will hold the instance. That way we can check whether or not the instance has been initialized, and then return it.
One key detail to mention, is the fact that the instance variable needs to be defined as static. That’s because it needs to be available inside the class without having to use the $this pointer (because the class cannot be instanciated with new). With this in mind, we can call the instance with the rezolution operator (::).
Now that we have discussed the interface of the class, we should describe how to access the instance. Since the member variable and the constructor are declared private, respectively protected, an instance cannot be created in the normal way. In this case, we need to use public Instance() method to access the memeber variable which holds the acutal instance. This functions checks if the private variable has been initialized, and if it hasn’t, it stores in it a new Singleton object. The final step is to return the member variable.
The code
As every coder knows, theory is better understood in practice. So let’s take a look at Singleton class:
class MySingletonClass { public static function Instance() { if( MySingletonClass::$_instance == NULL ) MySingletonClass::$_instance = new MySingletonClass(); return MySingletonClass::$_instance; } public function setVariable( $string = "" ) { $this->_memberVariable = $string; } public function getVariable() { return $this->_memberVariable; } protected function MySingletonClass() { $this->_memberVariable = "[default]"; } private static $_instance = NULL; private $_memberVariable; }
In order to describe better the characteristics of this patter, I have added a private variable which stores a string, and two public methods for setting that varibale and returning it. That way we can better undestand how the the instance changes throughout execution. Here is the main code of the application:
$singleInstance = MySingletonClass::Instance(); $singleInstance->setVariable("Hello, World!"); echo $singleInstance->getVariable(); $anotherInstance = MySingletonClass::Instance(); $anotherInstance->setVariable("<br />Godbye, World..."); echo $anotherInstance->getVariable(); echo $singleInstance->getVariable(); //Should display "Hello, World!", right? Wrong!
I have made two variables, which are in fact references to the Singleton instance, to show that if either of them calls setVariable(), the global instance will change, and it won’t matter which of them calls getVariable(). Another important thing to know the these two methods can be called without creating a variable which holds the Singleton instance, here’s how:
MySingletonClass::Instance()->setVariable("<br />Static function call."); echo MySingletonClass::Instance()->getVariable();
This has been a general description of the Singleton pattern. As an example of the pattern applied in practice, it can be used to create a class for handling a user. If the instance is initiated when the user loggs in, then the pattern can provide a way to access the information about that user, and the reference can call specific methods, anywhere in the application, without creating new objects. Another example would be a class for handling database connections and operations (like sending queries and displaying results).
You can see here a little demo of this code in action. Also, to see the complete code, you can download the files from here.