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?
Only the manufacturer company will need to know how to build the phone.
If the spec changes, the manufacturer will learn this and will distribute this to all the customers.
The price becomes less.
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.
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:
You do not need to modify the ReportGenerator base class.
You do not need to know how other report formats are handled.
You do not need to know how to get instance of the report generator of your desired format.
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.