Design Pattern is perhaps the mostly used buzz word for software professionals. The geeks of the industry always talk about it and the novices got tempted to learn design patterns reading the theory. There are lot of books and articles on different design patterns. In many interviews you may learn questions like do you know design pattern? Do you know XXX design pattern? Thus perhaps many software developers do have a look on design pattern tutorials before any interview to face. But really, you cannot learn design pattern in this way. As a matter of fact design pattern is not something to learn.
 
Design Pattern is not something to learn! Yes. Design patterns are nothing but some great ways to solve some classic software design scenarios. If you know the principles of software design and give effort to solve the design challenges in your projects, you will find, eventually you have used one or more design patterns even without knowing about that. And this is the way all the design patterns evolved. If a great software designer solves a design challenge there is every possibility, a design pattern will be used or may be a new design pattern will be created!
 
To me design patterns are some guidelines that all software developers should know so that when he works in any project he can solve the design challenges easily. So, it is more to be habituated and practiced than to be learned. When you read about any design pattern you should try to grasp what are the problems that design pattern is trying to solve and what was the thinking process to come up with that design pattern. And when you work in your project, before jump to code you need to find what are the design challanges exist in your work. Then, you should solve those design challenges and then start coding. During thinking about your design challenges if you remember any similar challenge that you found while reading about any design pattern go back to that, have a look on that and if it really solves your problem use that. Or perhaps use that in a way that suits in your scenario. The more you practice this procedure, less you will go back to read about patterns and better your designs will become.
 
I think you have already realized that, this write-up is just yet another write-up on Design Patterns. Design patterns are not any technology. Design patterns are actually some patterns of thinking to come up with a flawless design of your software requirements. Here I will try to derive towards 2 of the most frequently used design patterns from some scenarios. I will not tell the name of the patterns at the beginning of the examples so that your reading does not become tempted by some existing theoretical knowledge on these design patterns. You will find the pattern name at the end of each discussion.
 
Pattern 1: Let’s say you have developed a new operating system for smart phones named “Smart OS”. Now you want general people to use smart phones using this operating system. What will you do? You will create a specification for the OS and some instructions to manufacture the phone.
 
Let’s assume all the people of the world are capable enough to manufacture a phone using a spec. So, if you want to sell the OS to 1000 persons, the solution is all of those 1000 persons will learn the spec, create the phone and use it. Does this sound practical? Now, if you release a new version of "Smart OS"? Will all of those 1000 person learn the new spec again and update their phone? What if you need more customers? It really sounds weird. What is the solution then? I am sure you all know the solution.
 
For your new OS you will release the spec to a phone manufacturing company or maybe you will form one of your own (Like Apple builds iPhone on top of their own OS). The company will manufacture the phone using your OS and the end users will buy this from the manufacturer. So what should be the expected benefits here?
 
  1. Only the manufacturer company will need to know how to build the phone.
  2. If the spec changes, the manufacturer will learn this and will distribute this to all the customers.
  3. The price becomes less.
  4. The end user will just use the phone and will not need to know how this is created.
I am sure already you are thinking the example is too obvious. But similar scenario comes when we develop software. Sometimes, the situations are not too obvious.
 
For example, you are required to develop an html report generator. If you jump start to the code every possibility is that, you will create a class named HtmlReportGenerator. That will have a method named GenerateReport. This method will implement the report generation functionality. The client app will create an instance of the Html report generator class and will use the GenerateReport function to create the report.  
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Ok! That works fine. Now, your client wants a pdf report from you. What will you do?

Option 1: Create a PdfReportGenerator class.

Option 2: Re-factor the code. Remove HtmlReportGenerator. Instead create a general class
ReportGenerator. Create 2 methods. GenerateHtmlReport and GeneratePdfReport.
Option 3: Re-factor the code. Remove HtmlReportGenerator. Instead create a general class
ReportGenerator. Create the function GenerateReport as GenerateReport(ReportType rptType) taking report type as parameter.

Well, now if client wants reports in word format, xl format and few more formats, what will you do? Will you continue re-factoring? Or, will continue changing your report generator function? If you know the standard software design principles, these approaches will be a violation of Open-Close principle and Single Responsibility principle. Overall this will be a complete mess (BBOM).

Now, let's relate this with smart phone OS scenario. Though it was not very obvious, the Report generator example really has similarity with phone OS. So how could be the solution?

Simple! You create a company who will serve you the reports (As like mobile manufacturer company). You will serve data to the company and will tell which format of report you want. The company will deliver you the report. If new report format comes to the scenario, the company will learn how to do that and as a client you have to do nothing but ask for the correct type of report. See the code example below.

Now, using this design you have achieved the following benefits when a new report format needs to be added:

  1. You do not need to modify the ReportGenerator base class.
  2. You do not need to know how other report formats are handled.
  3. You do not need to know how to get instance of the report generator of your desired format.
  4. Your code becomes clean and free from BBOM.
Here you have one class named "ReportGeneratorCompany". As like the mobile phone manufacturer company for "Smart OS", ReportGeneratorCompany will know which format of report you need (The OS), It will create a report generator for you (perhaps the phone manufacturer team for "Smart OS" ) and the report generator will generate the report for you.
 
So, in both case ("Smart OS" and Report Generator), we saw how we can handle the scenario in smarter way. And believe me whenever, you do anything smartly in software, you are using a design pattern or as I said perhaps you are creating a new design pattern. I am sure many of you already have realized which design pattern I had used for report generator. Yes. This is Factory Pattern. Factory pattern is one of the widely used and simplest object creational design patterns. If the name of the "ReportGeneratorCompany" class were "ReportGeneratorFactory", it would have been more obvious to you. 
 
Here, the concept of the factory pattern is, you do not create instance of your object directly, rather you abstract away the instantiation logic in a factory class. When you need your object, you will ask the factory class and the factory class will provide you the instantiated object.
 
There are few other creational design patterns widely accepted as standards in software world. Those are: Factory Method, Abstract Factory, Builder, Prototype, etc.  In this write up we will discuss on 1 more creational design pattern. As before I would not tell now which one is that, rather I would like to derive to that pattern from design challenges.
 
Pattern 2: Let’s talk about the “Smart OS” again. Say in your smart phone OS you have some location specific features. For example you have location specific language support, you have location specific theme support, you have location specific hardware support etc. When you develop your OS, you listed out the features you are going to provide in your OS.  Now, the situation comes where few features will have different implementation based on your location. How will you handle this scenario?
 
Option 1: One way to solve this situation is have conditions in your Service provider classes (Language Service Provider, Theme Provider etc) and load the services based on the condition. In this case you have to provide the location information to the service providers.
 
 

 

What is your opinion on the above approach? I can see the following problem here:

  1. If a new location needs to be added we will have to modify the Service classes, which is a clear violation of Open-Close Principle.
  2. It is possible to load the OS with language from USA and theme from UK, which should not be allowed. 
  3. Code is un-organized and no point of extension is available.
This type of scenario comes every now and then in our software development practices. Here requirement shows that few objects need to be instantiated as a group. That means, if the location is USA, you must load all the USA based services for your device. So, you must enforce this.
 
In our previous pattern (Factory pattern) we saw how we can separate the object creation logic from the client using a factory. Should we be able to do something similar for the location based services? Well Let us try.
 
1. First of all we will need to abstract away the definition of the services. So, let’s create 2 abstract classes for language service and theme service.
2. Create concrete classes for different services based on location, inheriting from the abstract service classes. For example UsaThemeService class and UkThemeService class inheriting from ThemeService abstract class.

3. Create an abstract factory class which will have abstract definition of the methods to create all the services that needs to be created based on location.
4. Create concrete factory classes inheriting from the abstract factory class to create specific location based services.

 
 
 

5. Create the class for LocationBasedService. This class will create all the services instances based on the location provided and will load the services.
6. The client will know the location and will create service factory of that specific location. Eventually client will load the services.

 

The above way of implementation can further be improved using few more patterns perhaps like strategy, DI etc. However, that is out of the scope of this discussion.

So, we have created the location based services for the “Smart OS” in a new approach than the 1st approach we described. The new approach tries to solve the design challenges that we had on the first approach.

  1. Now, adding a new location based service is easy. You implement the services for the new location and as you already know what are the services you will need to implement from the LocationBasedServiceFactory you will not miss anyone. 
  2. This implementation will enforce you to initiate all the services of the same location and will prohibit you to initiate services from mixed locations.
  3. Service instantiation is abstracted away from the service itself, so, the client of the services do not need to know how to instantiate the services. 
  4. Your code has become extensible and manageable.
I am sure many of you already realized which pattern I have used here. Yes the pattern is “Abstract Factory”.
 
I would like to summarize the abstract factory pattern as it is little more complicated than the simple factory pattern. Following are the participators in the abstract factory pattern.
 
AbstractFactory – Abstract class to declare operations (LocationBasedServiceFactory) that create abstract products (theme service, language service).
ConcreteFactory – Implements AbstractFactory class to implement operations to create concrete products (UsaBaseServiceFactory).
AbstractProduct - Declares an abstract class for a type of product objects (ThemeService).
Product - Defines a product to be created by the corresponding ConcreteFactory; it implements the AbstractProduct class.
Client - uses the abstract classes declared by the AbstractFactory and AbstractProduct classes.
 
In this article, I have derived to explain 2 creational design patterns with examples. My goal was to help you gearing your thinking process to solve a problem in more patterned way. I hope to write on few structural and behavioral patterns in coming days too. More practice you do to achieve the best architecture for your work, the better your architectures will be.
 
I will appreciate your comments and feedbacks on this.

 

 

Comments

imon's picture

Nice article.

habib's picture

 

Nice and very well explained article.  Adding my personal opinion...
Design pattern is advanced object oriented programming technic by which we can solve some classic design problems/challenges. Design pattern is language independent. So code implementation might vary from c# and javascript(have a plan to write some design patterns implementation using javascript letter). Actually using design patterns we can get benifited from OOP features like abstraction, encaptulation, polymorphism etc. Before start design pattern I think we all need to full clear OOP features and implementation way. I saw many experiance developers not 100% clear of those features. That is very very unfortunate but true fact. If you have doubt then attach yourself as a member of any tecnical interview board and ask/listen oop related advanced questions and analysis the replies. My opinion is first step will be clear OOP concept first then play with design patterns.
Theare are so many design patterns already exists in the world (Not confuse architectual pattern and design pattern). But when talk about that first visualize Gang of Four design patterns(very very popular).
Now the debate may how to learn/understand those design patterns. Or  it is really learning things or only try to solve design challenges and that time evolve those pattern. My personal opinion is First design pattern need to learn and then try to fit it with real life senarios. It will clear the concept(Bridge between theory and practical life). But some times we see some pattern not fit with some senarios but we fit those forcely. That is so called anti pattern. That is another topics if possible letter talk with that. My logic to learn first is needed for clear the concept that what type of problem it deals with. It will help when we design any component and solve any design challenge (reuse the design). Another time it will help when we read any design pattern implemented code and try to extend those components. Without understand design pattern it will be very hard to work with those.  
So i think first step will be learn all of thouse then understand its features/natuare and limitations. 2nd step will be fit with real world design problem, if that oppertunity not come then see how to implement in any known product(your compnay or open source 3rd party).
In this article we see how to use abstract factory design pattern for Locationbased language and theme service. In asp.net mvc framework we see that MS team implement same abstract design pattern for build their controller. IControllerFactory is the abstarct factory class with 2 methods(CreateController,ReleaseController). They implement DefaultControllerFactory for create controller. We can easily create our own concreate ControllerFactory to implement that interface. Then how to inject that controller to the core framework. It is ControllerBuilder.Current.SetControllerFactory method. In our own concreate Controller Factory we can easily use any IOC container to solve tight coupling.
mahmud's picture

Ahasan Habib, Thanks for your nice opinions. 

Actually, if anybody does not know the basics of software design principles, he should do study on that and clear the concept first before moving to learn design pattern. When I wrote the article, I assumed that the audience already know design principles of designing a software that will satisfy a true object oriented model. You are correct, there are many experienced developers in the industry who do not have clear idea how to work in object oriented way. Few days back, I shared a video on software design principles created by one of our former colligue and requested to everyone to go through that. I got feedback, many of us already have gone through this. So, we should have some good understanding on OOP then. But again, if team feels they still need a training/discussion session on this, we may arrange a session. I am going to create a poll on facebook for this.

About Learning Design Pattern. I have no argument with you that, we should learn design pattern. My point is, we should not concerntrate too much on theory. I am sure both you and me are in same page that, it is more important to utilize the patterns in best way than to know the definitions of all the design patterns. That is why, I wanted to focus on the thining process and habituation of using different patterns. Cause, there are lot of engineers who know the definitions of all the design patterns but rarely used those. As I mentioned in the article - "To me design patterns are some guidelines that all software developers should know so that when he works in any project he can solve the design challenges easily. So, it is more to be habituated and practiced than to be learned. When you read about any design pattern you should try to grasp what are the problems that design pattern is trying to solve and what was the thinking process to come up with that design pattern. And when you work in your project, before jump to code you need to find what are the design challanges exist in your work. Then, you should solve those design challenges and then start coding. During thinking about your design challenges if you remember any similar challenge that you found while reading about any design pattern go back to that, have a look on that and if it really solves your problem use that. Or perhaps use that in a way that suits in your scenario. The more you practice this procedure, less you will go back to read about patterns and better your designs will become."

So, I hope both of us are thinking in the same way.

By the way, I really loved your comments. :)

 

 

 

 

kamruzzaman's picture

Thanks for such a nice and well organized presentation of the two creational design patterns with understandable examples. To master design patterns, we need to use these in practical life. But sometimes we cannot implement some patterns in our projects due to domain mismatch and after a certain period of time we more or less forget those patterns and cannot use them when applicable in some new requirements. To avoid this situation, my suggestion would be to read articles on the design patterns on a regular basis so that we can grow solid understanding on these and use them when situation demands.

ron's picture

Thanks Mahmud vai for coming up with this excellent writeup. The way of finding and implementing the pattern that you showed is just perfect and wonderful.

For me the challange is to identify the appropriate pattern from a real life system/SRS and then implement it. To achieve that expertise, I think

  • first it is important to know what are the design patterns and principles.
  • then looking for them around in real life systems to find out what patterns were applied there.

Also as titu vai said, reading journals on design patterns regularly can be a way. Some other options are

  1. always ask geeks/associates/communities whenever you stuck.
  2. attending similar events/sessions/discussions whenever possible.

I will share my similar experiences sometimes later.

Add new comment