This post is about the basic design patterns that are generally used in the software development to build a quality software product which is robust and flexible. A design pattern is a general reusable solution to the more commonly occurring problems in software Design. Patterns are formalized best practices that a software programmer can use to solve commonly occurring problems in a software application.
SOLID Design Principles
The design principles are set of guidelines which help us to avoid bad design.A design is said to be bad if it has any one or all the features listed below:
- Rigid: Hard to change and not flexible.If we have to change part of code, it forces us to change many other parts of the implementation.
- Fragile: Easily broken or damaged.Easily breaks the functionality of other parts. When we change part of code it breaks implementation in other parts.
- Immobility: Not reusable.We cannot reuse the code in other parts as it is difficult to disentangle from the current implementation.
- Single Responsibility Principle
- Open Close Principle
- Liskov's Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
Here we discuss just the principles which will help us to make the design better. In practice we have to put some extra effort to adopt these principles in our code by using the most appropriate pattern which fits our requirement.
1. Single Responsibility Principle
In this context responsibility means a reason to change the class. This principle states that if we have two reasons to change the class then we have to split the class into two different classes. Each class will handle only one responsibility and if we need to change in functionality, only the class which implements the functionality will be changed.
“A class should have one reason to change”
If the class has more than one reason to change then we need to divide the class.
Problem :
The above class has two responsibilities
· Get and set the account number
· Save the account details to database.
If we want to set the account holder name along with the account number, we need to change the implementation of the class set and get methods.
We already have the functionality to add the account details to the database and If we want to add the functionality to delete the account from database, we need to add new method to delete the account number.
So we have more than one reason to change the class .Single Responsibility principle states that if we have more than one reason to change the class, we need to divide the class into a smaller one.
The above class can be divided as follows:
Here we have subdivided the BankAccount class into BankAccount and MaintainAccount classes. So now if we want to get the account details from the database, we just need to change the MaintainAccount but not the BankAccount class.
The application design should take care of the frequent code changes done during development and maintenance phase of the application.When a new functionality is added to the existing application , usually requires many changes to existing implementation. These changes should be as minimum as possible as the existing implementation may be already unit/automatic tested.
2. Open Close Principle
The application design should take care of the frequent code changes done during development and maintenance phase of the application.When a new functionality is added to the existing application , usually requires many changes to existing implementation. These changes should be as minimum as possible as the existing implementation may be already unit/automatic tested.
Open Close Principle states that the design and coding should be such a way that new functionality should be added with minimum changes in the existing code. The design should be such that new classes can be added without affecting existing classes.
“Open for Extension But Closed for Modification”
Problem :
Here the GraphisEditor class is capable of drawing shape based on the object passed to the draw method. It is capable of drawing objects of type Circle and Rectangle.
But if we want to draw a new shape Square, we need to change the implementation of draw method in the GraphisEditor class. Every time there is a requirement to draw new shape, we need to change the draw method of GraphisEditor to accommodate the new shape. If the class which is changed is important and complex this can give bad results.
Class Diagram :
Implementation :
Solution :
We can ensure Open Close Principle by the use of abstract classes and concrete classes implementing the abstract class. In our example we can make the shape class abstract by adding abstract method to the shape class.
Class Diagram :
Implementation :
So if we want to extend the class GraphisEditor to support new shapes, the new shape has to extend the abstract class shape. So this way we are extending the GraphisEditor class but not modifying it.
Patterns :
The Design Patterns which attempt to follow the open close principle are
· Decorator Pattern
· Factory pattern
· Observer Pattern
3. Liskov's Substitution Principle
When we design and create applications, it is general practice to extend the existing classes(inheritance).
inheritance allows us to create new classes using already existing classes , but we can add new implementations to existing classes.
We must make sure that the new classes should just extend the base class rather than changing the functionality/implementation of the base class. Opposing this rule can give undesirable results.
Liskov's substitution principle states that if a program is using Base class reference , the reference to Base class can be replaced with the reference to the Derived class without affecting functionality of programming module.
Problem :
In the above example we have base class Add and the derived class MyAdd. Both the classes implement a method getSum(), But the implementation inside the two versions is different. The getSum() in the Add class returns sum of the arguments whereas the getSum() of the MyAdd class returns the difference of the arguments.
As per the rules of the contra-variance, i can pass the derived class object to a method that is expecting a base class object as its argument. To check this i have a class LiskovDemo which has a method getRes(Add a) which expects an object of type Add as its argument.But i can pass an object of type MyAdd following the rules of the contra-variance.
But if i do so it could result in unanticipated results to the user because the user is calling a method getSum and is expecting sum of the arguments . But if i pass the MyAdd object to the getRes method the user receives the difference of the arguments as opposed to the sum of arguments that is expected.
Note : This principle can be thought of as an extension to the Open Close Principle and it means that the derived classes should extend the base class without changing the behavior.
4. Interface Segregation Principle
Interface Segregation Principle states that the programmers should not be forced to implement the interfaces that they do not use. instead of one fat interface many small interfaces are preferred where each interface represents a sub module.
Fat Interfaces :
Suppose we want to add a new module to existing application based on the class MyClass which implements the interface MyInterface which has a few methods. The new module which i want to add needs to create an object of class which needs to implement only part of MyInterface. In order to create a concrete class from an interface , we need to implement all the methods of the MyInterface including the dummy methods which we do not require .
Such interfaces which force the programmers to implement dummy methods/functionality which they do not require are known as FAT or POLLUTED interfaces. The solution for such problems is to use small interfaces rather the Fat Interfaces.
"Small Interfaces are Preferred"
Problem :
Here we have an example which has an interface IEngineer that has two methods
· writeCode ()
· testCode ()
We want to have two classes Developer and ApplicationEngineer where both the classes need to implement whole or part of the IEngineer interface. There is no problem with the Developer class as he needs to do both writeCode () and testCode (). But in case of the ApplicationEngineer, he doesn’t write the code. His only job is to test the code written by the developers. Because the IEngineer interface forces the ApplicationEngineer class to implement dummy method for writeCode. This means that IEngineer is a fat interface.
Class Diagram :
Problem with the above design is that all the classes that implement IEngineer interface have to implement all the methods of the IEngineer interface. In case of Developer class there is no issue but the Tester doesn’t need to implement the writeCode() method as tester need not write the code whereas Developer has to both write the code and test the code. So here IEngineer is a fat interface.
Implementation :
Solution :
Solution for the above problem is to segregate the interface such that the concrete classes which implement the interface need not implement dummy methods. According to Interface Segregation Principle a flexible design will not have polluted or fat interfaces.
Class Diagram :
We can see that we have divided the IEngineer interface into two separate interfaces.
· IDeveloper
· ITester
The Developer needs to have the ability to both write the code as well as test it whereas the tester needs to only test the code, no need to write the code. To achieve this the developer class implements both the IDeveloper and ITester interfaces. As the Tester needs to only test the code and not to write the code he needs to implement ITester interface and no need to implement IDeveloper.
Implementation :
Patterns : The Design Patterns that follow the Open Close Principle are
- Adapter Design pattern
5. Dependency Inversion Principle
Any software application design usually consists of low level and high level classes.The low level classes implement the basic/core functionality whereas the high level classes implement the business logic which uses the low level classes.
The usual way of implementing such cases is to first write the low level classes and then write the high level classes based on the low level classes. This way of implementation seems to be logical.
But what happens if we need to change the low level class. We need to change the high level class also as per the new low level class. So the design is not flexible and we can overcome this limitation by using abstractions.
. Low level classes should not depend on high level classes and vice verse.
. Abstractions should not depend on details, Details should depend on abstractions.
“Details should depend on abstractions”
Problem :
In the below example we have a manager class and a Worker class. The Manager class is a high level class and the Worker is a low level class. The Manager class is composed of the Worker class (member variable) and has a method manage which calls the work method of Worker object.
Suppose if we want the manager to manage new kind of worker SuperWorker, we have to change the Manager class to accommodate this requirement. So every time we have a new class to support we need to change the implementation of the Manager class.
This problem can be overcome by the use of abstractions rather than the concrete classes.
Implementation :
Solution :
The above problem can be resolved by introducing an abstraction layer between the high level classes and low level classes. We can have an interface IWorker which will be implemented by all the workers.
The Manager class will have IWorker variable as the member so that it can process all the classes that implement. It can extend its functionality to support any new class that implements the IWorker interface.
Class Diagram :
The Manager class can accept any new class that implements the IWorker interface.
- No changes in the manager class required.
- No need to change the existing unit tests.
Implementation :
When this principle is applied, high level classes cannot work directly with the low level classes, they interact with low level classes via abstractions. So the high level classes
Patterns :
The Design Patterns which attempt to follow the Dependency Inversion principle are
· Template Design Pattern
We should not apply this principle blindly as this results in many interfaces and classes. We need not apply this principle if the High level class doesn't need to change.
**********************************************************************************************************************************************************************************************************************************************************
Introduction to Design Patterns
Design patterns are the best practice followed by the developers. The patterns are the solution to the general problems faced during the software development. The developers came up with the best solution to certain problems found on a trial and error basis over a period of time.
Learning the design patterns help the inexperienced developers to improve their software design skills in a faster way. The concept of the design patterns was initiated by a group of four software developers known as the Gang Of Four(GOF). According to the GOF the design patterns are categorized into
Creational Patterns : The creational design patterns provide a mechanism to create objects of desired classes hiding the creational logic . These patterns provide a way to avoid the raw method of creating objects using new operator. These patterns decide which object has to be created base on the situation.
Structural Design Patterns : These patterns mainly deal with classes and the object composition. Composition and inheritance are the building blocks of the structural patterns. These provide simple ways to have a good relationship between objects.
Behavioral Design Patterns : These patterns are mainly concerned about the communication between the objects.
1. Creational Design Patterns
Method 5 : Using enum
This is the most simplest way of achieving singleton pattern as it uses important features of a java enum
Implementation :
Client code to use this singleton enum object is different when compared to a class object.
**********************************************************************************************************************************************************************************************************************************************************
Design patterns are the best practice followed by the developers. The patterns are the solution to the general problems faced during the software development. The developers came up with the best solution to certain problems found on a trial and error basis over a period of time.
Learning the design patterns help the inexperienced developers to improve their software design skills in a faster way. The concept of the design patterns was initiated by a group of four software developers known as the Gang Of Four(GOF). According to the GOF the design patterns are categorized into
Creational Patterns : The creational design patterns provide a mechanism to create objects of desired classes hiding the creational logic . These patterns provide a way to avoid the raw method of creating objects using new operator. These patterns decide which object has to be created base on the situation.
Structural Design Patterns : These patterns mainly deal with classes and the object composition. Composition and inheritance are the building blocks of the structural patterns. These provide simple ways to have a good relationship between objects.
Behavioral Design Patterns : These patterns are mainly concerned about the communication between the objects.
1. Creational Design Patterns
Creational Patterns mainly deal with the object creation mechanism. The main aim of the creational patterns is to create objects suitable to the situation. The basic form of the object creation uses following syntax.
MyClass myobject = new MyClass ();
This is as good as hard coding the values and could result in serious design problems. Creational Patterns are composed of two dominant ideas
1. Encapsulating knowledge about concrete classes.
2. Hiding how instances of concrete classes are created.
Creational
Patterns are basically divided into two categories:
1. Object Creation patterns (OC): Object creation patterns defer part of the object
creation to other object.
2.
Class Creation Patterns (CC): Class creation patterns defer part of the object creation to
subclass.
Few well
known creational patterns are:
1.
Factory Design Pattern (CC): Allows class to defer object creation to sub classes.
2 .
Abstract Factory Pattern: Provides interface for creating
objects of related and dependent classes without specifying the object’s
concrete class.
3.
Builder Design Pattern: Separates construction of complex object from its
representation so that same construction process can be used to create
different representation.
4.
Prototype Pattern (OC): This pattern specifies the kind of object to create using
prototypical instance and creates new objects by doing the prototype.
5.
Singleton Pattern: This pattern makes sure that a class has only one instance
and provides global point of access to it.
Consider
applying Creational patterns when :
1.
A
system should be independent of how objects are created.
2.
A
set of related objects is designed to be used together.
3.
Hiding
implementation of class library of a product revealing only their interfaces.
4.
A
class wants its sub classes to implement the object it creates.
5.
Class
instantiations are specified at runtime.
6. There
must be a single instance of a class and client can access it all the time.
7.
Instance
should be extensible without being modified .
Class Diagram :
A class diagram that most creational patterns have in common is as shown :
Now that we have an overview on what we mean by creational patterns, now it is time to get a clear understanding on their usage.
Class Diagram :
A class diagram that most creational patterns have in common is as shown :
Now that we have an overview on what we mean by creational patterns, now it is time to get a clear understanding on their usage.
1 . Factory Design Pattern :
Definition :
The factory pattern defines an interface for creating an object but delegates
the object creation to the sub classes.
Problem :
1. In some
cases the object creation mechanism is so complex and requires some level of
abstraction and the client code doesn't need to know these complexities.
2. In some
cases object creation is scattered and repetitive in some parts of the code .
Factory
pattern resolves these issues by creating an interface which specially creates
an object and gives implementation classes to decide on which class to
instantiate.
Objective : The objective should be
1. client
should be unaware of the object creation mechanism
2. client
should access the objects through the interface.
But we can overcome this drawback by adding additional code
as shown.Here all the shape classes remain same but we have to modify the
ShapeFactory and Client application.
With the above implementation if we want to support new shapes like ellipse , there is no need to change the shape classes(circle,rectangle,square) and ShapeFactory classes. We just need to register the class with the ShapeFactory and can get the object from the ShapeFactory.
2. Factory Method Pattern :
The factory method pattern is also a class creation pattern , provides an interface for creating object but the choice of which object to create is decided by the subclasses with object creation being deferred to runtime. This pattern is also known as Virtual Constructor.
The factory method should not be confused with the normal or simple factory. We cant call it as a factory method pattern if we use a factory methods. In order to justify it as a factory method pattern it should involve inheritance and the factory method should be implemented by the derived class or concrete classes implementing the factory interface.
Features :
Defines interface to create objects, but let the sub-classes decide which class to instantiate.
Refers to the natively created objects via a common interface.
The factory method pattern is useful when
Object creation involves a complex process and we want to separate this process from the composing class.
To avoid duplication of the object creation code
In some cases the composing class does not have the information required to create the required object.
Class Diagram :
In the class diagram we have 4 important components :
Product (Interface ) : Defines the interface of the objects the factory creates.
Concrete Product : Implements the product interface.
Factory (Interface) : Also called as creator as it declares the method to create objects.
Concrete Factory : Implements the Factory Interface.
Implementation :
The above code is a client code that shows how to use the factory to create the objects of the desired classes.
3. Abstract Factory Design pattern
This pattern can be defined as a factory of factories. This means that abstract factory pattern works with a super factory that in turn works with sub factories to create an object of a class . This pattern uses an interface that creates a set of factories and each factory is responsible for creating objects of a set of related classes.
to be added..........
4. Builder Design Pattern :
The builder pattern's intention is to building complex object using an algorithm in such a way that its construction is independent of the way it is represented. By doing so the construction process used to create a complex object can also be used to represent the object in different ways.
The builder design pattern allows us to create the object step by step and use the same object creation process to create different representations.
"Separate the construction of a complex object from its representation so that the same construction process can create different representations"
In a builder design pattern Director is the only one who knows the details of the object that will be created.
The factory design patterns have a problem when :
Class Diagram :
Builder : Specifies an abstract interface for creating parts of the product object.It defines steps for the creation of the product object.
Concrete Builder : Constructs the parts of the product by implementing builder interface also returns the product object.
Director : Constructs the object using builder interface.
Product : The object under construction.
Implementation :
Let us consider an example of a restaurant which serves different types of food which differs based on the region like North Indian, South Indian , Chinese etc.
The above code shows the product interface and the product class whose object needs to be created.
Class Diagram :
Implementation :
The picture gives an overview of the implementation that we use to demonstrate the factory pattern. We are going to create a Shape interface and concrete classes implementing the Shape interface. A factory class ShapeFactory is defined as a next shape. Factory Pattern Demo, our demo class will use ShapeFactory to get a Shape object. It will pass information (CIRCLE/RECTANGLE/SQUARE) to ShapeFactory to get the type of object it needs.
ShapeFactory is used by client to generate the objects of his
choice.
Although the
above implementation looks fine and simple, it doesn't follow the Open Close
Principle of "SOLID" design principles. Every time I have to support
a new shape, I have to change the implementation of the ShapeFactory. This is
the drawback of factory pattern.
With the above implementation if we want to support new shapes like ellipse , there is no need to change the shape classes(circle,rectangle,square) and ShapeFactory classes. We just need to register the class with the ShapeFactory and can get the object from the ShapeFactory.
2. Factory Method Pattern :
The factory method pattern is also a class creation pattern , provides an interface for creating object but the choice of which object to create is decided by the subclasses with object creation being deferred to runtime. This pattern is also known as Virtual Constructor.
The factory method should not be confused with the normal or simple factory. We cant call it as a factory method pattern if we use a factory methods. In order to justify it as a factory method pattern it should involve inheritance and the factory method should be implemented by the derived class or concrete classes implementing the factory interface.
Features :
Defines interface to create objects, but let the sub-classes decide which class to instantiate.
Refers to the natively created objects via a common interface.
The factory method pattern is useful when
Object creation involves a complex process and we want to separate this process from the composing class.
To avoid duplication of the object creation code
In some cases the composing class does not have the information required to create the required object.
Class Diagram :
Product (Interface ) : Defines the interface of the objects the factory creates.
Concrete Product : Implements the product interface.
Factory (Interface) : Also called as creator as it declares the method to create objects.
Concrete Factory : Implements the Factory Interface.
Implementation :
The above group of code represents the product(Shape) and concrete products(circle,rectangle and square)
The above piece of code shows the factory (ShapeFactory) and ConcreteFactory (CircleFactory, SquareFactory and RectangleFactory)
3. Abstract Factory Design pattern
This pattern can be defined as a factory of factories. This means that abstract factory pattern works with a super factory that in turn works with sub factories to create an object of a class . This pattern uses an interface that creates a set of factories and each factory is responsible for creating objects of a set of related classes.
to be added..........
4. Builder Design Pattern :
The builder pattern's intention is to building complex object using an algorithm in such a way that its construction is independent of the way it is represented. By doing so the construction process used to create a complex object can also be used to represent the object in different ways.
The builder design pattern allows us to create the object step by step and use the same object creation process to create different representations.
"Separate the construction of a complex object from its representation so that the same construction process can create different representations"
In a builder design pattern Director is the only one who knows the details of the object that will be created.
The factory design patterns have a problem when :
- The object to be created is very complex and has a lot of attributes that needs too many arguments to be passed from the client program
- Some of the parameters are optional and we have to pass null to these optional parameters.
Class Diagram :
Builder : Specifies an abstract interface for creating parts of the product object.It defines steps for the creation of the product object.
Concrete Builder : Constructs the parts of the product by implementing builder interface also returns the product object.
Director : Constructs the object using builder interface.
Product : The object under construction.
Implementation :
Let us consider an example of a restaurant which serves different types of food which differs based on the region like North Indian, South Indian , Chinese etc.
The above code shows the product interface and the product class whose object needs to be created.
One of the concrete builder class called NorthMeals.
This is another concrete builder class called SouthMeal.Now we need to get our Director class.
This is the creator class that is the only class that knows which object is created. The way we can use this creator class is shown below.
Here we can see that we have a builder object of type NorthMeal and a creator called creator of type MealCreator. The creator first decides or initializes the contents of meals object. Once we are done with the representation or how the meal object looks like, we can create the object get the object of type Meal and is returned by creator.
5. Prototype Design Pattern :
This pattern is an object creational pattern as the part of the object creation pattern is deferred to other objects.
Let us consider an object which is very complex and creation of one object of such type uses lot of resources and can say a costly affair. So we can think why not create one object and use this existing object to create a modified version of existing object.
I would copy the existing object to a new object i want to create ,we use the java cloning mechanism to do this. Later i would modify the contents of this object to create one of my choice.
We can use the prototype design pattern when :
1. We want to hide the complex object creation process from the client.
2. When the object creation process is costly or takes more resources.
3. When objects we want to create are similar to existing objects.
We can use the existing object to form the skeleton of the new object we want to create.
Cloning is a good thing we have in java because if we want to copy the contents of one object to other. Normally what we do is create a new object of same type and copy the contents to the new. But there is an implicit facility available in java called clone.
Class Diagram :
The class diagram contains three parts :
Client : Creates the object
Prototype : Forms an interface of the object we want to create and declares the clone method.
Concrete Prototype :Implements the clone method declared in the interface and takes care of cloning the object and return it.
We can follow two methods to realize the prototype design pattern :
1. we can use the default cloning mechanism provided by the java.
2. We can define our own cloning method and do the copy of objects.
Method 1 :
Here we have an interface IMeal and NorthMeal as its implementation. NorthMeal class implements the cloneable interface provided by java.
Here i have taken one more class called complement just to explain the drawback of the default cloning mechanism provided by java
NorthMeal class that implements IMeal and also contains an object of type complement.
As we can see that the NorthMeal class implements clone method and calls the super.clone method inside.
This method returns a cloned object of the NorthMeal class. Below is the client code that shows how to create a clone of existing object.
Below is the code that uses the prototype design pattern to create object that is a copy of the already existing object of type NorthMeal class.
Method 2 :
In the previous sample we have seen how to use the default clone method provided by the java.Now we will see how we can define our own method to achieve the same implementation.
Note : All the code in the previous sample can be used here except the NorthMeal Class. In this class instead of the default clone method we use our own method.
NorthMeal class doesn't need to implement the cloneable interface.So the class header changes as
So instead of using the overridden clone method inside NorthMeal class, we can write our own method getClone().
So instead of calling NorthMeal meal2 = meal1.clone() we can call
So this is it we are done with our own version of the clone method.
clone() vs getClone() :
clone() is provided by java and it performs shallow copy. So it works fine in case of the primitive data types.
But when i start to clone the objects that contain reference types we are performing shallow copy . This means that the reference type part of the clone and original object are referring to the same portion of the memory. This could result in a lot of problems because when we change the contents if the reference type of the clone it results in changes to the original object.
The drawback of the getClone() is that it is fine to write a method to copy the contents of the original object to the clone given that our class has very less members . But as this number grows it is very time consuming or error prone to write all the code each time we had to write a new version of the getClone().
So the solution is to use the clone() method provided by the java but use any technique like serialization or copy constructors for example to perform deep copy instead of shallow copy.
6. Singleton Design Pattern :
Sometimes we want to have only one instance of an object existing all the time like Window Manager or a Print spooler. It is the simplest design pattern and involves only a single class.
The motivation to use the singleton design pattern is
to have only one instance of an object
to be able to access this single instance globally.
Class Diagram :
The singleton pattern as i told is the most simple design pattern as it involves only a single class. But there are several things we have to know about its implementation.
Method 1 :
This is the simplest way of realizing the singleton pattern . But this approach has a problem in case of a multi-thread environment as there is a chance that two threads can try to access the code inside the check
if(instance == null)
{
...........................
time consuming code like a for loop
...........................
instance = new Singleton();
}
There is a chance that when first thread is executing the time consuming code and second thread enters the
if condition as still instance is null . In this case both the threads are clear to create an instance of the Singleton class. This clearly violates the rule of singleton to have only one instance of Singleton to exist at a time.
To avoid this we need to follow the double locking mechanism.
Method 2 : Lazy Initialization
This is also known as the double locking mechanism as we make a double check if the instance is null. We synchronize the second if condition with Singleton.class as shown below.
This double locking mechanism makes sure that only one thread has access to the code that generates new instance of the Singleton class.
Method 3 : Eager Initialization
As we have seen that the method 2 uses the thread synchronization to avoid the problems in the multithreaded environment. But this double locking mechanism can be avoided by using a technique called eager initialization .
Implementation :
Here we create the instance of the object when the class is accessed for the first time and the initialization is done at the class level as shown below :
Advantages of Eager Initialization :
- The instance is not constructed until the class is used or in other words the object is constructed when the class is used for the first time.
- No need to synchronize the getInstance() method
- Complex condition checks can be eliminated.
- Final keyword ensures that the object can not be modified after it has been created.
Method 4 : Static Block Initialization
In the eager initialization we have initialized the static variable at the time of the declaration . The same functionality can be achieved using the static blocks . Java provides a facility to have anonymous static block of code that will be the first part of the code when class is loaded by the JVM.
So we can be assured that this is the part of code which is called even before constructor or any other method of the code or even before data members are initialized.
So we can be assured that this is the part of code which is called even before constructor or any other method of the code or even before data members are initialized.
Implementation :
Method 5 : Using enum
This is the most simplest way of achieving singleton pattern as it uses important features of a java enum
- Enum constants are by default static and final.
- Enum can have constructor but it has to be definitely private.
- Enum can have member functions and also variables and are private by default.
Implementation :
Client code to use this singleton enum object is different when compared to a class object.
At last we are done with the singleton pattern.
With this we can conclude our discussion on creational patterns and in the next session we will look at behavioral patterns.
*********************************************************************************************************************************************************************************************************************************************************
2. Behavioral Design Patterns :
These patterns are mainly concerned with how the objects communicate with each other to achieve the required workflow. The communication between objects means the exchange of the data that happens between the objects to get a task done.
The list of design patterns is as follows :
- Chain Of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- Strategy
- Template
- Visitor
- Null Object
Let us start the tour of behavioral patterns with the Chain of Responsibility.
1. Chain Of Responsibility :
Chain of Responsibility pattern is a combinations of source of request and a chain or linked list of the objects which act as the handlers of the responsibility. Each handler has a part of the code that determines the request it can handle. Along with the responsibility of handling the request , the handler also has to pass the responsibility to the next node in the chain of objects.
Responsibilities of each node in the chain are :
1. Handle the response if it can
2. If it can not handle the request ,pass the responsibility to next node in the chain.
In the above picture each alphabet represents a node that can handle a request. If the first one can not handle the request then the responsibility is passed on to the next node.
Class Diagram :
The class diagram explains the whole story where each concrete handler forms a node and client is the source of the request.
Implementation :
Let us take an example where we have chain of objects and each can handle a mathematical operation. The client will send the data and the requested operation . We first send it to the first object in the chain and if it can not handle, it passes the data and request to the next handler in the chain.
The first handler in the chain can do the addition operation,second can do subtraction, third can do the multiplication and fourth can do the division. Suppose if we send a data with two numbers and the operation will be division. Then the first handler passes it to the second, second passes it to third and third to fourth and the fourth handler can handle the division . So the fourth handler can do the division and return the result.
ChainSubtraction :
ChainMultiplication :
ChainDivision :
Now we have the client code that creates the request or command that has to be handled by the chain of handlers.
Client :
Features of Chain Of Responsibility :
That completes our discussion on the Chain of Responsibility Pattern.
2. Command Design Pattern :
The command design pattern is also known as the action or transaction pattern. Here a request is wrapped under an object as command and is handed over to invoker. The invoker tried to find the appropriate receiver that can handle the command and passes the command to this receiver . The role of receiver is to execute the command and get the job done.
Features :
Class Diagram :
Flouro Class :
Now re need to implement the client code that triggers the command.
Observer Interface :
Concrete Observer :
The class diagram explains the whole story where each concrete handler forms a node and client is the source of the request.
Implementation :
Let us take an example where we have chain of objects and each can handle a mathematical operation. The client will send the data and the requested operation . We first send it to the first object in the chain and if it can not handle, it passes the data and request to the next handler in the chain.
The first handler in the chain can do the addition operation,second can do subtraction, third can do the multiplication and fourth can do the division. Suppose if we send a data with two numbers and the operation will be division. Then the first handler passes it to the second, second passes it to third and third to fourth and the fourth handler can handle the division . So the fourth handler can do the division and return the result.
The numbers class represent the data and method is the request that the handler has to either handle or pass it on.
Chain forms the interface that all the handlers have to implement and each handler represents a mathematical operation.
ChainAddition :
ChainMultiplication :
ChainDivision :
Client :
Features of Chain Of Responsibility :
- The sender will not know which object in the chain will handle the request.
- Every node in the chain can decide if it can handle the request.
- Nodes have the capability to pass the request to next handler in the chain.
- There is a possibility that none of the nodes will handle the request.
That completes our discussion on the Chain of Responsibility Pattern.
2. Command Design Pattern :
The command design pattern is also known as the action or transaction pattern. Here a request is wrapped under an object as command and is handed over to invoker. The invoker tried to find the appropriate receiver that can handle the command and passes the command to this receiver . The role of receiver is to execute the command and get the job done.
Features :
- Encapsulates request as an object.
- Allows saving of requests in queue.
- Sender and receiver are decoupled.
- parameterize client with different requests.
- Helps to implement callback in java.
Class Diagram :
Command : Declares an interface for all the commands and provides the execute method that asks the receiver to perform some task.
Concrete Command : Provides implementation of the execute method that defines the one or more taks to be done by the receiver.
Invoker : Holds the command and can can get the command to execute a request by calling execute method.
Receiver : Has the knowledge of what to do to carry out the request.
Client : Creates concrete commands and assigns the receiver for a command.
Implementation :
To implement this pattern we will consider an example where using a switch we turn on or off any given light in the room. In our implementation we have interface command and its implementation in the form of TurnOn() and TurnOff().
Command Interface :
command interface forces all the classes that implement command interface to implement execute() method.
Concrete Command :
We have created four classes that implement the command interface like TurnOn,TurnOff,TurnOnAll and TurnOffAll.
TurnOn : Implements the execute method to turn on any light.
TurnOff : Implements the execute method to turn off any light.
TurnOnAll : Implements the execute method to turn on all lights.
TurnOffAll : Implements the execute method to turn off all lights.
invoker :
Now we have to implement an invoker that contains a command and asks the handler to handle the request.
Receivers : We have a set of receivers all implementing the Light class.
Bulb Class :
We have created four classes that implement the command interface like TurnOn,TurnOff,TurnOnAll and TurnOffAll.
TurnOn : Implements the execute method to turn on any light.
TurnOnAll : Implements the execute method to turn on all lights.
TurnOffAll : Implements the execute method to turn off all lights.
invoker :
Now we have to implement an invoker that contains a command and asks the handler to handle the request.
Receivers : We have a set of receivers all implementing the Light class.
Bulb Class :
Flouro Class :
Now re need to implement the client code that triggers the command.
This ends our discussion on the command pattern.
3 . Memento Design pattern :
This pattern is mainly used as undo or Ctrl+z with a bit more options or control of the point to which we want to rollback to. Memento pattern is used to save the internal state of the object and rollback to this state in future.
Some real time examples for this pattern are
- The undo button in the calculator that can be used to check the previous state of the calculation.
- The rollback option in a database where we can save the state of the database and rollback the state of the database to the state before committing some data to the database.
- SVN version control where we have the list of the commits in the log of the version. We can rollback to a particular version that we want to.
Class Diagram :
As we can see this pattern consists of three important building blocks.
Originator : This is the object whose state has to be saved. It has the method to create a memento. This state can be saved and retrieved for future undo.
Memento : This object acts as the memento and contains the state of the originator.
CareTaker : This object stores the mementos and provides methods to save and retrieve the memento.
Implementation : We will consider the example where we keep the track of the name of a person that keeps changing.
Memento :
Originator :
CareTaker :
As we can see this pattern consists of three important building blocks.
Originator : This is the object whose state has to be saved. It has the method to create a memento. This state can be saved and retrieved for future undo.
Memento : This object acts as the memento and contains the state of the originator.
CareTaker : This object stores the mementos and provides methods to save and retrieve the memento.
Implementation : We will consider the example where we keep the track of the name of a person that keeps changing.
Memento :
Originator :
CareTaker :
Client Code :
Memento design pattern can be expensive sometimes if the amount of information to be saved is high and we have to maintain a large record of the states.The size of the application becomes high. This is it for the Memento Design Pattern.
4. Observer Design Pattern :
This pattern works similar to the way we subscribe to a monthly or weekly magazine. Initially we subscribe to the magazine for a limited period of time. So we will be receiving the magazine for the period we have subscribed .
Once the period expires the magazine will not be delivered i.e our subscription period has ended and we can either extend the subscription or the subscription will be terminated by default by the magazine people. Suppose if we do not want to receive the magazine before the subscription period has ended , we can do that by sending unregister request.
This pattern is also known as publish-subscribe pattern and will be generally used in complex patterns like MVC etc
Note : In this pattern the Subject will maintain a list of the observers who have registered and will be notified in case of the subscribed event.
Class Diagram :
In the class diagram we can see a subject to which all the observers will subscribe and will be notified in case of an event.
Implementation :
Subject Interface :
Concrete Subject :
Concrete Observer :
Client Code :
Usage of Observer Pattern :
We need use the observer pattern when :
Multiple objects are dependent on the state of an object and all these objects need to change their state or perform some action based on the state of the subject.
When an object is waiting for a notification from the subject based on which it will decide the state it has to be in or take some action.
5. Visitor Design Pattern :
The Visitor design pattern has motivation to separate the algorithm from the object on which it operates.This allows one or more operations to be applied to many objects at run-time. Downside of this pattern is we need to know in advance the visitable classes. If we want to support new visitable class we need to change all the implementation classes of visitor interface.
3. Structural Design Patterns :
Structural Design patterns are are used to simplify the design by identifying a simple way to realize the relationships between entities. The structural patterns category has the following design patterns :
- Composite
- Bridge
- Adapter
- Decorator
- Flyweight
- Proxy
1. Composite Design Pattern :
The motivation behind the composite pattern is to treat group of objects as a single object. Here we compose a tree structure containing objects to form part as well as whole hierarchy.This pattern comes under the structural patterns category as it creates a tree structure of group of objects.
In some cases the when the program needs to deal with a tree structure, it needs to treat leaf and nodes uniformly. For example in a file system folders are like branches and files are like leaves. Folders contain files and also in some cases it can also have sub folders. Usually the files and folders have some operations in common like copy, rename,delete etc , we can treat both files and folders as the same by defining an interface.
This pattern creates a class that contains its own objects and provides way to modify this group of objects.
A composite design pattern treats each node in two ways : node and leaf. Here a node can have one or more child nodes or leaves whereas the leaf can not have any child nodes.
Class Diagram :
Composite Pattern Tree Structure :
We can visualize that both composite and leaf in the above tree structure have to implement the same interface. Each composite can have a list of composite and leaves and interface forces both composite and leaf to implement some common methods.
Implementation :
We will consider an example of an office which contains many category of employees like manager, developer, HR etc. This is a scenario where the hierarchy of the employees forms a tree with each developer having a manager and each manager has some developers reporting to him and also a manager above or reporting to him. This holds a perfect scenario as basically all the people working in the office are employees.
So here the manager classes become composite and the developer objects are the leaf nodes. We need to have an interface or an abstract class which forms the base class for all the composite and leaf nodes.
Parent Class for All Nodes
This abstract class forms the Component in the above class diagram . Here we can see that we have a method displayDetails that has the common functionality for all the nodes.
Composite : In our case all the manager objects are the composite objects or folders that may either have sub folders(manager or developer).
Leaf : In our case all the developer objects form the leaf nodes and this means that they are like files that can not hold any other files unlike the folders. Developer can not be a manager to other developers ...funny.
finally we have the client code that uses the above tree structure and we print out the tree structure of the employee hierarchy.
Key points : we use the composite pattern
When we want to implement the part-whole hierarchies of the objects.
When we want the client code to ignore the difference between the composition of objects and individual objects alone.
Drawback of the composite pattern is that some classes are forced to implement methods which they need not( Fat interfaces, see the Interface segregation principle above)
2 . Bridge Design Pattern :
Bridge Design Pattern is useful when we need to decouple an abstraction from its implementation so that two can vary independently. This is categorized as the structural pattern as this introduces a bridge between the abstraction and implementation so that both can vary independently.
The bridge is usually an interface which acts as a bridge which makes the functionality of concrete classes independent from the interface implementer classes. Both the extensions of the abstract classes and the implementer classes of the interface can be altered independently.
This pattern is basically an extension of the statement "Prefer composition over inheritance"
Class Diagram :
In the class diagram we can see four important blocks.
1. Abstraction :
defines an abstraction
Maintains reference to the object of type implementer
2. RefinedAbstraction : Extends the interface defined by the Abstraction.
3.Implementer :
defines the interface for the implementation classes.
This interface doesn't have to correspond to the abstraction. In fact the two are usually different.
The interface usually defines the primitive functionality where as the abstraction has the business logic of the whole implementation.
4. ConcreteImplementer : This is the concrete implementation of the Implementer.
To explain this we take an example of shapes and colors.
Implementer Interface :
Concrete Implementer :
Concrete Implementer:
Abstraction Implementation :
Refined Abstraction :
Suppose if i want to create a different shape like triangle that has the same ability as the circle(different colors) we can do that as follows.
3. Adapter Design Pattern :
Adapter design pattern as the name suggests, acts as an adapter or the bridge between two incompatible object types. This pattern involves a single class that is responsible to join functionality of two incompatible or independent interfaces.
The adapter class makes two incompatible interfaces to work together . Normally these incompatible interfaces can not work together because of the incompatibility of interfaces.
Power adapter is the best real world example of the Adapter as it acts as the converter or adapter between the UK system(50 hz) power supply and the US system(60 hz). If it was not this adapter all the electrical appliances that were manufactured in US could not be used in the UK or other parts of the world.
Class Diagram :
Implementation : The adapter design pattern can be implemented two ways
- using Inheritance
- using Composition
Here we are going to consider an example of a voltage adapter. initially we have a socket that gives out a 120 volts. But what if we want a factor of 120 volts based on the device connected to the socket. So we use an adapter that gives out voltage that is factor of 120 volts. In case of both inheritance and composition all the classes are same except the adapter class.
Target :
This is the object that is under the spotlight and is the object or data that is of our interest.
Target :
This is the object that is under the spotlight and is the object or data that is of our interest.
Adaptee : This is the class that wants to fit in to the situation where it can not serve the purpose. It is capable of only generating 120 volts and we are in need to get the volts that is a factor of 120 volts depending on the device connected.
Adapter Interface : This interface is the skeleton of the adapter class we are going to create.
Using Inheritance :
Adapter pattern can be implemented using inheritance . Here the adaptee class which wants to change according to the requirement or want to change itself to look like a different class adapter. So the adaptee forms the base class and the adapter is derived from the adaptee.
Using Composition :
In this case the adapter class holds an instance of the adaptee class so that we can call all the methods of the adaptee class like getvolts() in our case.
In this case the adapter class holds an instance of the adaptee class so that we can call all the methods of the adaptee class like getvolts() in our case.
Note : Composition is a better approach over the inheritance as it has got some advantages over the inheritance like less fragile, loose coupling etc..
4. Decorator Design Pattern :
The decorator design pattern is helpful when we want to extend the functionality of an object at run-time with out altering its structure.We can achieve the same behavior using the inheritance because we create an object using the properties of an already existing class. But these changes apply to all the objects that we create using the derived class.
But the intention or motivation behind the Decorator design pattern is that we want to add new functionality to a single object but not all the objects of the class.
This pattern is also known as the wrapper because we create a wrapper class around the object that we want to extend and delegate all the operations to the new wrapper class.
Features of Decorator Pattern :
- This pattern is used to enhance the functionality of an object at run-time.
- Other instances of this class are not affected.
- This pattern is based on the abstract classes and creating concrete implementation of the abstract class.
Class Diagram :
In the above class diagram we have an item called component which is an interface and forms the base for whole implementation. The concretecomponent is an implementation of the component interface and this is the component we want to decorate.
In order to achieve this we create an abstract class Decorator and this decorator has holds a member of type component and also implements the component and also implements the component interface.
The ConcreteDecoratorA and ConcreteDecoratorB are the implementations of the decorator and add some new features to the object of type component. This can be clearly understood with the help of below exampl.
Implementation :
let us take an example of shapes where we have circle,rectangle etc. Here we use the decorator pattern to add some extra features like border, fill color etc to these shapes.
Component :
Concrete Component :
In the client code we can see that initially we created a circle and later on we added extra features to this circle like border, filled color etc. But if we create new objects of type circle, these circles are plane ( no border and color).
5. Flyweight Design Pattern :
The main objective of this pattern is to reduce the no of objects created to reduce the memory footprint and increase the performance. This pattern is part of the structural pattern community because it effects the structure of the application by reducing the no of objects.
The way this pattern works is that it will save any object created if it is first of its kind. In the future if we need to create an object of similar kind , instead of creating new object we can use the already saved object as the skeleton to create a new object . In fact we do not save the complete object but only part of it. The part of object we are going to save is the base of the objects we want to create. It has only the properties which are common to all the objects of its kind.
When ever we want to create a new object we take the base object which we have already saved and add some features to it to get the object with the desired properties.
Class Diagram :
Implementation :
Let us consider an example where i have to generate circles and the circle has an intrinsic property color and all the others are extrinsic . Intrinsic property is the property on which we group the circles like red circle, green circle. The remaining properties like position and radius vary.
The shape is the interface based on which we form the flyweight object which in our case is the Circle.
The Circle object has many properties like color,position and the radius. But the color of the circle is the intrinsic property and the radius and position form the extrinsic properties.
The ShapeFactory here is the Fly Weight factory that generates the intrinsic flyweights . As we can observe the flyweight objects are generated only if it is the first object with the specified intrinsic value. If an object with the same property already exists then we just get the reference of the existing object and add the extrinsic properties to this object.
We should notice it is not the responsibility of the factory to fill in the extrinsic properties . The client code takes care of this task of filling the extrinsic properties as shown below.
Drawbacks :
let us take an example of shapes where we have circle,rectangle etc. Here we use the decorator pattern to add some extra features like border, fill color etc to these shapes.
Component :
Concrete Component :
Decorator :
Concrete Decorator :
Another Concrete Decorator :
Client Code :
5. Flyweight Design Pattern :
The main objective of this pattern is to reduce the no of objects created to reduce the memory footprint and increase the performance. This pattern is part of the structural pattern community because it effects the structure of the application by reducing the no of objects.
The way this pattern works is that it will save any object created if it is first of its kind. In the future if we need to create an object of similar kind , instead of creating new object we can use the already saved object as the skeleton to create a new object . In fact we do not save the complete object but only part of it. The part of object we are going to save is the base of the objects we want to create. It has only the properties which are common to all the objects of its kind.
When ever we want to create a new object we take the base object which we have already saved and add some features to it to get the object with the desired properties.
Class Diagram :
Let us consider an example where i have to generate circles and the circle has an intrinsic property color and all the others are extrinsic . Intrinsic property is the property on which we group the circles like red circle, green circle. The remaining properties like position and radius vary.
The shape is the interface based on which we form the flyweight object which in our case is the Circle.
The Circle object has many properties like color,position and the radius. But the color of the circle is the intrinsic property and the radius and position form the extrinsic properties.
The ShapeFactory here is the Fly Weight factory that generates the intrinsic flyweights . As we can observe the flyweight objects are generated only if it is the first object with the specified intrinsic value. If an object with the same property already exists then we just get the reference of the existing object and add the extrinsic properties to this object.
We should notice it is not the responsibility of the factory to fill in the extrinsic properties . The client code takes care of this task of filling the extrinsic properties as shown below.
Benefits :
- Reduces the no of objects at run-time which saves the memory.
- Centralizes the state for many virtual objects into a single location.
Drawbacks :
- Intrinsic flyweights can not act independently.















































































No comments :
Post a Comment