When we design an application, there are different design considerations that come to our mind. Some of them are
- Designing the different Layers of the applications
- Choosing the best deployment strategies
- Data Validations or validation framework
- Managing different configuration
- Implementing different Security Standards
- Designing the Middle Tier services
- Thinking of cloud compatibility
- Integrating to different systems
- Testing strategies
- Scaling up the applications
As we keep developing the applications, we learn real-world problems. A few of them are performance-based design and development, high availability, scalability, security, project management, caching, and testing techniques.
Most of the times, the customer's business is complex, and we are required to manage technical & business complexity to build the robust application. We achieve these design considerations by using different design patterns and design principles.
Choosing the right pattern for a particular requirement is an important factor in the designing of an application. It is very common mistake that we try to apply the design pattern, as we know a specific pattern which eventually brings lots of technical difficulties in the application in the future.
When designing a system, we should visualize the pattern, and understand which pattern it may fit into. The patterns differ based on how the objects are created, how they are organized, and how they behave in different situations. Design and architecture of the application evolve day by day, as we add our day to day thought process to make it simpler, make the application loosely coupled, and make it more testable.
We have GOF patterns, MVC, MVVM, Repository, Lazy Loading, provider pattern, asynchronous patterns and many more.
We have different GOF Design patterns which have been proven for a long time, let us go to some of the design patterns which are widely used and understand where to use which pattern with some easy examples.
Singleton
In this pattern, only one single instance can be created throughout the lifetime of the application. From the starting point of the application to the end of the application execution, only one instance takes care of achieving the functionalities.
For easy understanding, consider the king in a kingdom. He will create different rules and regulations to rule the kingdom.
Singleton patterns are commonly used in -
a. Configuration Management
Consider we have lot of configuration related xml files, dll, or a shared resource which needs to be added at the starting of the application. Throughout the life of the application, the configuration value should be there and it should not be changed again and again; at that time, singleton is a good fit.
b. Logging
Logging is one of the common requirements of the application, where the single logger instance would be available at the start of the application. When we use Log4Net or NLog for logging, a single logger instance will take care of logging.
Factory
In Factory pattern, the factory class wants to decide which subclass will be used to create the objects .This object creation is determined dynamically depending on the situation or condition.
Consider a situation where our application has different data sources of the application, such as Oracle, SQL Server, MySQL etc. The application needs to connect to different databases depending on the situation. So, we need to create the instance of the Database instance class, Database connection.
Different types of reports
In the application, we have to create different types of reports, like excel, pdf, crystal report etc. Based on the user selection report type, we can create the instance of different report class type.
Different types of accounts in a banking system
The banking system has different types of accounts for customers, like Checking account, Saving account, or Loan account. Based on the different types of accounts, being passed from the customer, the specific account instance will be created and the required action will be called from that object.
Abstract Factory
Abstract factory design pattern creates a factory of related or group of objects without explicitly specifying their classes.
Consider we have an application and we want to create a family of related objects like Samsung, Nokia or Blackberry. These are different families of objects. Abstract Factory uses the factory pattern for creating instance of several classes during the implementation.
System.Data.Common.DbProviderFactory class in ADO.NET represents the set of methods for creating instances of a provider's implementation of the data source. Classes are examples of abstract factory design pattern.
AdapterAdapter pattern is a pattern which is used to match two incompatible interfaces. When we have two different interfaces which do not match, the adapter classes work as a wrapper to match it.
Example
Consider we have a third party tool which does not have proper interface or code to fit into our application. To match it, we need to extend the third party code as a wrapper.
External WCF call without data validation
In one of my applications, we had to call an external WCF service, but before calling the WCF service, we had to manipulate some of the data and had to validate certain logic in the part of WCF call. In this case, we created a wrapper WCF service which does manipulation, validation, and calls the WCF service call.
The ADO.NET providers, eg System.Data.SqlClient.SqlConnection, System.Data.OleDb.OleDbConnection etc. Each provider is an adapter for its specific database.
Observer
It is the pattern which communicates to the subscribed objects when there is a change in the subject.
Example
Customers get notified by email, message in the mobile, hard copy of letter in postal address when the loan application is approved by the bank.
Different Alert Systems
Customers, Dealers, Agents get notified when there is a change in the price of the stock.
Parent Pages which are opened in a single page application get notified when there is a change in data in a pop up.
Events and delegates in the .net framework are examples of observer pattern.
Facade
When we design a system, we call different services, external service calls, database calls which altogether makes the system complex. Actually, exposing internal calls is not important to the clients. Only client needs to call some code that internally can communicate to the different systems or different services involved in it.
Façade design pattern is used when a system is very complex or difficult to understand how it is working internally.
Example
Different Bank ATM cards Working process in a single ATM Machine
When withdrawing money from an ATM we are not aware of how the transaction happens internally from the same bank or a different bank.
From the .net framework System.Xml.Serialization.XmlSerializer.XmlSerializer is an example of façade pattern. It hides a complex task converting objects into xml formats behind the scenes.
Template
The same business rule applies for the entire client with some variation. The method skeleton can be put in an abstract class and different client implementation can be put in the derived class.
Example
In a report generation module, customer requirement is to generate different type of reports either HTMLReport, PDF report , excel report or in a flat file report where the report header , logo and footer keep constant .
Master page in ASP.NET is an example of template pattern.
Chain of Responsibility
In this pattern we have chains of objects which keep on passing on different chains.
Loan or Leave approval process where a request passes between multiple stages. We apply for a loan it goes to validation, verification, approval process. In each process there should be a set of rules where they can approve a certain stage or pass the request chain to next immediate chain flow.
Another example to understand the chain of responsibility is the clarification on the requirement in an agile team.
Development team gets a defect which has a complex algorithm
Development team reached to QA team, QA team tried to answer the questions but is unable to answer. QA team emailed the questions to product owner. The product owner finally passed the question to stakeholder. The Email chain keeps increasing from developer to QA then Product owner and finally the stakeholder. If any of the chain can know the perfect answer the chain stops there.
Exception handling mechanism in C# is the good example of chain of responsibility pattern where we have lots of exception types ArgumentException,OutOfMemoryException,NullPointerException,FormatException depending on the exception chain will capture the exception.
Decorator
Decorator pattern attaches additional responsibilities to an object dynamically and transparently. Decorators provide a flexible alternative to sub classing for extending functionality.
In any organization we see lot of projects, many variety of skill sets depending upon the customer projects.
In a MS.NET team different teams are there, but the base skill sets are ASP.NET, C#, SQL Server.
The new requirement 1 will keep on asking give me candidates with additional skill sets of WCF, WEB API as a top up skills
The new requirement 2 will keep on asking give me candidates with additional skill sets of WCF, ANGULAR JS as a top up skills
The new requirement 3 will keep on asking give me candidates with additional skill sets of WEB API, ANGULAR, WCF and ASP.NET MVC top up skills
On this example, the Base Skill set object gets appended to different skill sets dynamically, based on the project need.
Different stream classes in .NET framework Stream, MemoryStream, BufferedStream, FileStream are example of decorator pattern
Conclusion
I hope you got some information on GOF design pattern. Please put your comments or suggestions below .Thank you very much for reading this article.