Design Patterns
Design
patterns are considered to be best solution for application design based
problems. When we design application or have to implement any task. We have
multiple ways to perform that task but we should try to perform that task in
best way. There are many tasks/problems, we face frequently whilst development
or designing application so there are best solutions for such common problems
given by gurus. Design patterns help a lot to minimize frequent and complex
problems.
Following
are few examples (problems), which could help you in understanding what kind of
problems are resolved by design patterns.
- You want to
undo work done by user one or multiple times
- Suppose you
don’t need to let create multiple objects of same class at a time in any
case.
- You don’t know
exact class type of which you would need to create object whilst
programming/coding.
- You need to
change behavior of object without changing of class implementation.
- You might need
to have different behavior of same object on change of state of object.
Aforementioned
points are just to give you sense of types of problems/tasks, you could have
whilst application development and designing.
There
are very famous and worth readable, Gang of Four Patterns. Some of them, which
are most frequently being using or you may say being needing is going to be
discussed below.
Before
digging into them, I must like to say couple of things about design patterns:
design patterns are very easier than rocket science and as a web developer or
architect should have familiarity with them. At a web developer level, design
patterns are being heavily ignored. Design patterns enhance your approach to
solve problems and differentiate you by others and these are the basic things
to get success in this field so must go for it.
We
divide design patterns into three categories, according to their purpose.
- Creational
Patterns
- Structural
Patterns
- Behavioral
Patterns
Creational Patterns
As
name implies, creational design patterns are all about creation of objects. Object
creation is a responsibility, which if dealt in a wrong way could increase
complexity and create design issues of application.
There
are several design patterns regarding that responsibility to minimize
complexity and reduce design issues.
Following
are few but most commonly used creational design patterns:
- Singleton
Pattern
- Factory
Pattern
- Abstract
Factory Pattern
- Builder
Pattern
- Prototype
Pattern
Some of the design patterns are discussed below:
Singleton
Pattern
Singleton
design pattern is every easy, very famous and widely used design pattern. It
actually restricts creation of object. We use singleton pattern, when we need
to create only one
object of the class and don’t want to create any
more object of that class until that object exist in memory.
Implementation
pseudo code
- Create Public
class
- Create Private
constructor of that class (so out of the class, object couldn’t be
instantiated)
- Create class
level private static instance of that class (static class level instance,
so could be accessible by static method of the class)
- Make static
method of that class (so could be call from out of the class without using
object of that class)
- Check either
instance of the class, which we created in step 3 is null if yes then
create and return new instance of the class otherwise return already
created instance
Sample
Code
//step 1
public class SingletonPattern
{
//step 2
private SingletonPattern() { }
//step 3
private static SingletonPattern _instance = null;
//step 4
public static SingletonPattern GetInstance()
{
if (_instance == null)
{
_instance = new SingletonPattern();
}
return _instance;
}
}
Factory
Pattern
Factory
design pattern is very widely used in .net framework. It takes responsibility for
creation of object at run time without specifying exact class type. We use
factory pattern, when we want to delegate
responsibility of creation of object to its sub class or other (helper) class.
Implementation
pseudo code
- Create
interface or abstract class
- Create two
classes which implement above created interface (or inherit in case of
abstract class)
- Create class
(to whom you want to delegate responsibility of object creation of classes
created step 2)
- Create static
method whose return type is interface or abstract class created in step 1.
- Static method
gets information to know, which type of object need to create and return.
Sample
Code
//step 1
public interface IVehicle
{
string Drive();
}
//step 2
public class Car: IVehicle
{
public string Drive()
{
return "ghooooooooonnnnn";
}
}
public class Bike : IVehicle
{
public string Drive()
{
return "gheeeeeeeeeennnnn";
}
}
//step 3
public class VehicleFactory
{
//step 4
public static IVehicle CreateVehicle(string
type)
{
//step 5
switch (type)
{
case "car":
return new Car();
case "bike":
return new Bike();
default:
throw newArgumentException("Invalid
Vehicle Type!");
}
}
}
Strategy
Pattern
Strategy
pattern gives us power of using appropriate algorithm, according to the need,
dynamically (at runtime). There are many situations, where we prefer strategy
patter like, calling appropriate method according to the need of user, swapping
algorithms at runtime or have to do some localization.
To
clear picture in mind regarding strategy pattern, I would like to create here
some very simple scenario.
Everyone
is familiar with tax. Every country has different taxation algorithms
(formulas), so if you get a chance to write such a system, which needs to call
different methods/algorithms/formulas according to different scenario at
runtime. Strategy pattern is there for you.
Implementation
pseudo code
- Create interface
(or abstract class) and create method (so tax could be charge, country
wise)
- Create classes
for different countries and implement that method and apply the formula of
deducting tax, according to tax rules.
- Create class
which could use this pattern or you may say used to call tax method
dynamically, according to country.
- Create
instance of interface (created in step1) and create variable to contain
salary amount, at class level.
- Create method
to set country information at run time.
- Create method
to call interface method which has been implemented by other classes to
calculate tax, according to country.
Sample
Code
//Step 1
public interface ITaxStrategy
{
double CalculateTax(double
amount);
}
//Step 2
public class USATax: ITaxStrategy
{
public double
CalculateTax(double amount)
{
return amount * 1.05;
}
}
public class PakistanTax: ITaxStrategy
{
public double
CalculateTax(double amount)
{
return amount * 1.37;
}
}
//Step 3
public class MonthlyPay
{
//Step 4
private ITaxStrategy
iTaxStrategy;
public double
SalaryAmount;
//Step 5
public void
SetTaxCountry(ITaxStrategy tax)
{
iTaxStrategy =
tax;
}
//Step 6
public double
ApplyTax
{
get
{
return iTaxStrategy.CalculateTax(SalaryAmount);
}
}
}
MonthlyPay pay = new MonthlyPay();
pay.SalaryAmount = (double)10;
USATax usaTax = newUSATax();
pay.SetTaxCountry(usaTax);
pay.ItemWithTax;
PakistanTax ukTax = newPakistanTax();
pay.SetTaxCountry(ukTax);
pay.ApplyTax;
Command Pattern
As name implies, command pattern is used to
keep record of multiple commands, we can undo or redo commands through it. It’s
quite common, we do some operations and sometimes we need to undo our work for
some reason. It’s always a good practice and some times necessary for some
applications to empower user for undoing operations. You may take example of
programming in visual studio environment.
You make some method and later make some
modifications and after some time you realized, you are not suppose to make
those changes, so you need to undo your operation and keep pressing (ctrl+z) J
Implementation
pseudo code
- Create
some class
- Create
interface (abstract class) with method to undo operation
- Create
another interface (abstract) which implement interface (created in step 2)
- Create
class which implements interface created in step 3 and create class level
instance of class (created in step 1) and variable to keep prior operation
(number)
- In
constructor assign current operation object to instance of class (created
in step 1)
- Implement
methods of that interface which class is implementing
Sample
Code
//step 1
public class Operations
{
private int
taskNumber;
public Operations()
{
taskNumber =
1;
}
public int TaskNumber
{
get
{
return taskNumber;
}
set
{
taskNumber
= value;
}
}
}
//step 2
public interface IBaseCommand
{
void Undo();
}
//step 3
public interface ITaskCommand
: IBaseCommand
{
void AssignTask(int
taskNumber);
}
//step 4
public class TaskCommand
: ITaskCommand
{
private Operations
myTasks;
private int
OldTaskNumbers;
//step 5
public TaskCommand(Operations
o)
{
myTasks = o;
}
//step 6
public void
AssignTask(int taskNumber)
{
OldTaskNumbers
= myTasks.TaskNumber;
myTasks.TaskNumber = taskNumber;
}
public void Undo()
{
myTasks.TaskNumber = OldTaskNumbers;
}
}
Proxy
Design Pattern
Proxy
design pattern is used when we have too heavy object and don’t wanted to load
all whole object in one go to avoid slow performance and to avoid consuming too
much memory resource. Sounds good, isn’t it.
There
are many ways to have its example, when you view google earth, it doesn’t show
up complete image of universe. It just loads some part of that image. Suppose
if it loads complete image of universe, then? J
Simpler
example could be when you load very heavy document (pdf), it loads first few
pages, and when you navigate to other pages, it loads other pages then in
memory.
Implementation
pseudo code
- Create class
whose object could have long data
- Create class
level variable to contain data
- Implement
constructor which get portion number and set that portion
- Create method
to return portion (show data partially)
- Create class
which compose object of class (created in step 1)
- Create
instance of class (created in step 1)
- Assign null to
instance in constructor
- Create property
which show/return data
Sample
Code
//step 1
public class Page
{
//step 2
private string
pageText;
//step 3
public Page(int
pageNumber)
{
if (pageNumber == 1)
{
pageText = "1st page of document";
}
else if (pageNumber
== 2)
{
pageText = "2nd page of document";
}
else
{
pageText = "Page Not Found";
}
}
//step 4
public string
GetPageText
{
get
{
return pageText;
}
}
}
//step 5
public class Document
{
//step 6
private Page page;
private int
pageNumber;
//step 7
public Document()
{
page = null;
}
public int PageNumber
{
get
{
return pageNumber;
}
set
{
pageNumber
= value;
}
}
//step 8
public string FullDescription
{
get
{
if (page == null)
{
page = new Page(pageNumber);
}
return page.GetPageText;
}
}
}
Conclusion
Design patterns are easier than rocket science to understand and implement and 101% useful as good designed application are easily maintainable and expendable. It might take bit more time in start but overall it increase development performance and application performance.
Kindly post comments if you have any queries or anything you wanted to say related to this article.
Thanks,