Computer Science Design Patterns
From Wikibooks, the open-content textbooks collection
The term Design Patterns can confuse you at first, or it can sound like something incredibly difficult, but in fact it's nothing more than convenient ways of reusing your code.
Design Patterns are patterns in design that keep coming back in software design and are written down and named. Imagine yourself working in a project team and someone just wrote a class and is trying to explain you that only one instance is allowed. Instead the person could simply say "The class I just wrote is a Singleton".
Patterns can be classified in different categories, of which the main categories are: Creational Patterns, Structural Patterns and Behavioral Patterns.
Contents |
[edit] Creational Design Patterns
[edit] Abstract Factory
Definition: A utility class that creates an instance of several families of classes. It can also return a factory for a certain group.
[edit] Builder
Definition: Separates the construction of a complex object from it's representation.
[edit] Factory
Definition: A utility class that creates an instance of a class from a family of derived classes
[edit] Prototype
Definition: Copies or clones an existing class instance instead of creating a new instance. This can be useful in cases where creating a new instance of a class is more expensive.
[edit] Singleton
The term Singleton refers to an object that can be instantiated only once. In programming languages like Java, you have to create an instance of an object type (commonly called a Class) to use it throughout the code. Let's take for example this code:
Animal dog; // Declaring the object type dog = new Animal(); // Instantiating an object
This can also be written in a single line to save space.
Animal dog = new Animal(); // Both declaring and instantiating
At times, you need more than one instance of the same object type. You can create multiple instances of the same object type. Take for instance:
Animal dog = new Animal(); Animal cat = new Animal();
Now that I have two instances of the same object type, I can use both dog
and cat
instances separately in my program. Any changes to dog
would not affect the cat
instance because both of them have been created in separate memory spaces. To see whether these objects actually are different we do something like this:
System.out.println(dog.equals(cat)); // output: false
The code returns false
because both the objects are different. Contrary to this behavior, the Singleton behaves differently. A Singleton object type can not be instantiated yet you can obtain an instance of the object type. Let us create a normal object using Java.
class NormalObject { public NormalObject() { } }
What we have done here is that we have created a class (object type) to identify our object. Within the braces of the class is a single method with the same name as that of the class (methods can be identified by the usage of parentheses at the end of their names). Methods that have the same name as that of the class and that do not have a return type are called Constructors in OOP syntax. To create an instance of the class, the code can not be much simpler.
class TestHarness { public static void main(String[] args) { NormalObject object = new NormalObject(); } }
Note that to encourage the instantiation of this object, the constructor is called. The constructor as in this case can be called outside the class parenthesis and into another class definition because it is declared a public accessor while creating the Constructor in the above example.
Now we will create the Singleton object. You just have to change one thing to adhere to the Singleton design pattern: Make your Constructor's accessor private.
class SingletonObject { private SingletonObject() { } }
Notice the constructor's accessor. This time around it has been declared private. Just by changing it to private, you have applied a great change to your object type. Now you can not instantiate the object type. Go ahead try out the following code.
class TestHarness { public static void main(String[] args) { SingletonObject object = new SingletonObject(); } }
The code returns an error because private class members can not be accessed from outside the class itself and in another class. This way you have disabled the instantiation process for an object type. However, you have to find a way of obtaining an instance of the object type. Let's do some changes here.
class SingletonObject { private static SingletonObject object; private SingletonObject() { //Instanciate the object. } public static SingletonObject getInstance() { if (object == null) { object = new SingletonObject(); // Create the object for the first and last time } return object; } }
The changes involve adding a static class member called object
and a public static
method that can be accessible outside the scope of the class by using the name of the Class. To see how we can obtain the instance, lets code:
class TestHarness { public static void main(String[] args) { SingletonObject object = SingletonObject.getInstance(); } }
This way you control the creation of objects derived from your class. But we have still not unearthed the final and interesting part of the whole process. Try creating multiple instances and see what happens.
class TestHarness { public static void main(String[] args) { SingletonObject object1 = SingletonObject.getInstance(); SingletonObject object2 = SingletonObject.getInstance(); } }
Unlike multiple instances of normal object types, multiple instances of a Singleton are all actually the same object instance. To validate the concept in Java, we try:
System.out.println(object1.equals(object2)); // output: true
The code returns true
because both object declarations are actually referring to the same object. So, in summarizing the whole concept, a Singleton can be defined as an object that can not be instantiated more than once. Typically it is obtained using a static custom implementation.
In some applications, it is appropriate to enforce a single instance of an object, for example: window managers, print spoolers, database access, and file systems
[edit] Singleton & Multi Threading
Java uses multi threading concept, to run/execute any program. Consider the class SingletonObject discussed above. Call to the method getInstance() by more than one thread at any point of time might create two instances of SingletonObject thus defeating the whole purpose of creating the singleton pattern. To make singelton thread safe, we have different options:
1. Synchronize the method getInstance, which would look like:
public synchronized static Singleton getInstance(){ if ( instance == null ) { instance = new Singleton(); } return instance; }
Synchronizing the method guarantees that a call to the method cannot be interrupted.
2. Synchronize the block, which would look like:
public static Singleton getInstance(){ synchronized(className.class){ if ( instance == null ) { instance = new Singleton(); } } return instance; }
Synchronizing the block does the same as the synchronizing on the method. The only advantage is that you can synchronize the block on another class/object.
3. Another approach would be to create a singleton instance as shown below:
class SingletonObject { public final static SingletonObject object = new SingletonObject(); private SingletonObject() { //Exists Just to avoid instantiation. } public static SingletonObject getInstance() { object = SingletonObject.object; return object } }
[edit] Examples
[edit] Structural Patterns
[edit] Adapter
Used to change the interface of one class to another. It is a so called wrapper class.
[edit] Bridge
[edit] Composite
A Singleton goes into a Factory Method as a Visitor and an Observer, and gets out as Decoratored as an Interpreter
[edit] Decorator
[edit] Facade
One class has a method that performs a complex process calling several other classes.
[edit] Flyweight
Shared information are stored once.
[edit] Proxy
Control the access to an object.
[edit] Behavioural Patterns
[edit] Chain of Responsibility
[edit] Command
Command pattern is an Object behavioural pattern that decouples sender and receiver. It can also be thought as an object oriented equivalent of call back method.
Call Back: It is a function that is registered to be called at later point of time based on user actions.
public interface Command{ public int execute(int a, int b); }
public class AddCommand implements Command{ public int execute(int a, int b){ return a + b; } }
public class MultCommand implements Command{ public int execute(int a, int b){ return a * b; } }
public class TestCommand{ public static void main(String a[]){ AddCommand add = new AddCommand(); add.execute(1,2); // returns 3 MultCommand multiply = new MultCommand(); multiply.execute(2,3); // returns 6 } }
In the above example, it can be noted that the command pattern decouples the object that invokes the operation from the ones having the knowledge to perform it.
[edit] Interpreter
[edit] Iterator
[edit] Mediator
This pattern helps to model a class whose object at run-time is responsible for controlling and coordinating the interactions of a group of other objects
[edit] Memento
Briefly, the Originator (the object to be saved) creates a snap-shot of itself as a Memento object, and passes that reference to the Caretaker object. The Caretaker object keeps the Memento until such a time as the Originator may want to revert to a previous state as recorded in the Memento object.
[edit] Observer
Define a one-to-many dependency between objects so that when object changes state, all its dependents are notified and update automatically.
[edit] State
Allow an object to alter its behaviour when its internal state changes. The object will appear to change its class.
[edit] Strategy
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
[edit] Template Method
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of algorithm without changing the algorithm's structure.
[edit] Visitor
Represent an operation to be performed on an element of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
[edit] Other Patterns
[edit] Model-View-Controller Pattern
The model-view-controller pattern is a very common pattern that splits a module into 3 pieces. The model, the view, and the controller. The Model is the actual data representation (for example, Array vs Linked List) or other objects representing a database. The View is an interface to reading the model (perhaps implemented as an Active Server Page (ASP) or a fat client GUI. The Controller (perhaps implemented in Java as a Servlet or EJB Session Bean) provides the interface of changing or modifying the data, and then selecting the "Next Best View" (NBV).
Newcomers will probably see this "MVC" model as wasteful, mainly because you are working with many extra objects at runtime, when it seems like one giant object will do. But the secret to the MVC pattern is not writing the code, but in maintaining it, and allowing people to modify the code without changing much else. Also, keep in mind, that different developers have different strengths and weaknesses, so team building around MVC is easier. Imagine a View Team that is responsible for great views, a Model Team that knows a lot about data, and a Controller Team that see the big picture of application flow, handing requests, working with the model, and selecting the most appropriate next view for that client.
Erm, someone please come up with a better example than the following... I can't think of any
For example: A naive central database can be organized using only a "model", for example, a straight array. However, later on, it may be more applicable to use a linked list. All array accesses will have to be remade into their respective Linked List form (for example, you would change myarray[5] into mylist.at(5) or whatever is equivalent in the language you use).
Well, if we followed the MVC pattern, the central database would be accessed using some sort of a function, for example, myarray.at(5). If we change the model from an array to a linked list, all we have to do is change the view with the model, and the whole program is changed. Keep the interface the same but change the underpinnings of it. This would allow us to make optimizations more freely and quickly than before.
One of the great advantages of the Model-View-Controller Pattern is obviously the ability to reuse the application's logic (which is implemented in the model) when implementing a different view. A good example is found in web development, where a common task is to implement an external API inside of an existing piece of software. If the MVC pattern has cleanly been followed, this only requires modification to the controller, which can have the ability to render different types of views dependent on the content type requested by the user agent.