Tuesday, November 25, 2014

Object Oriented Patterns and Princples

Design Patterns are very important for us to understand if we want to build a software which is re-usable,scalable, maintainable etc. Design patterns are high-level abstract solution templates. Think of design pattern as blueprint for solutions rather than solutions themselves.The origins of the design patterns that are prevalent in software architecture today were born from the experiences and knowledge of programmers over many years of using object-oriented programming languages.A set of the most common patterns were cataloged in a book entitled Design Patterns: Elements of Reusable Object-Oriented Software, more affectionately known as the Design Patterns Bible. This book was written by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, better known as the Gang of Four (GoF). They collected 23 design patterns and organised them into 3 groups:- Creational(5), Structural(7) and Behavioral(11).


Creational patterns deal with object construction and referencing. They abstract away the responsibility of instantiating instances of objects from the client, thus keeping code loosely coupled and the responsibility of creating complex objects in one place adhering to the Single Responsibility and Separation of Concerns principles. Following are the patterns in the Creational group:
➤ Abstract Factory: Provides an interface to create families of related objects.
➤ Factory: Enables a class to delegate the responsibility of creating a valid object. 
➤ Builder: Enables various versions of an object to be constructed by separating the construction
for the object itself.
➤ Prototype: Allows classes to be copied or cloned from a prototype instance rather than creating
new instances.
➤ Singleton: Enables a class to be instantiated once with a single global point of access to it.


Structural patterns deal with the composition and relationships of objects to fulfill the needs of larger systems. Following are the patterns in the Structural group:
➤ Adapter: Enables classes of incompatible interfaces to be used together. This pattern is covered
in this chapter.
➤ Bridge: Separates an abstraction from its implementation, allowing implementations and abstractions to vary independently of one another.
➤ Composite: Allows a group of objects representing hierarchies to be treated in the same way
as a single instance of an object. 
➤ Decorator: Can dynamically surround a class and extend its behavior. 
➤ Facade: Provides a simple interface and controls access to a series of complicated interfaces
and subsystems. 
➤ Flyweight: Provides a way to share data among many small classes in an efficient manner.
➤ Proxy: Provides a placeholder to a more complex class that is costly to instantiate. 


Behavioral patterns deal with the communication between objects in terms of responsibility and algorithms. The patterns in this group encapsulate complex behavior and abstract it away from the flow of control of a system, thus enabling complex systems to be easily understood and maintained. Following are the patterns in the Behavioral group:
➤ Chain of Responsibility: Allows commands to be chained together dynamically to handle a request. 
➤ Command: Encapsulates a method as an object and separates the execution of a command from its invoker. 
➤ Interpreter: Specifies how to evaluate sentences in a language.
➤ Iterator: Provides a way to navigate a collection in a formalized manner.
➤ Mediator: Defines an object that allows communication between two other objects without them knowing about one another.
➤ Memento: Allows you to restore an object to its previous state.
➤ Observer: Defines the way one or more classes can be alerted to a change in another class.
➤ State: Allows an object to alter its behavior by delegating to a separate and changeable state
object. 
➤ Strategy: Enables an algorithm to be encapsulated within a class and switched at run time to
alter an object’s behavior. 
➤ Template Method: Defines the control of flow of an algorithm but allows sub classes to override
or implement execution steps. 
➤ Visitor: Enables new functionality to be performed on a class without affecting its structure.

To choose when to use which design pattern is the biggest challenge. When it comes to design patterns, there is no substitute for studying. The more we study the more we become equipped about the pattern. Below are the guidelines that might come handy when choosing a design pattern-

➤ We can’t apply patterns without knowing about them. The first important step is to expand our knowledge and study patterns and principles both in the abstract and concrete form. We can implement a pattern in many ways. The more we see different implementations of patterns, the more we will understand the intent of the pattern and how a single pattern can have varying implementations.

➤ Do we need to introduce the complexity of a design pattern? It’s common for developers to try to use a pattern to solve every problem when they are studying patterns. We always need to weigh the upfront time needed to implement a pattern for the benefit that it’s going to give.Remember the KISS principle: Keep It Simple, Stupid.

➤ Generalize the problem; identify  the issues we are facing in a more abstract manner. Look at how the intent of each pattern and principle is written, and see if your problem fits with the problem that a particular pattern or principle is trying to solve. Remember that design patterns are high-level solutions; try to abstract the problem, and don’t focus too hard on the details of specific issue.

➤ Look at patterns of a similar nature and patterns in the same group. Just because we have used a pattern before doesn't mean it will always be the correct pattern choice when solving a problem.

➤ Encapsulate what varies. Look at what is likely to change in our application. If we know that a special offer discount algorithm will change over time, look for a pattern that will help you change it without impacting the rest of your application.

At the core of all design patterns is the design principles. Software design principles represent a set of guidelines and principles that helps us to avoid having a bad design. The design principles are associated to Robert Martin who gathered them in "Agile Software Development: Principles, Patterns, and Practices". According to Robert Martin there are 3 important characteristics of a bad design that should be avoided:-rigidity, fragility, immobility.The S.O.L.I.D. design principles are a collection of best practices for object-oriented design. All of the Gang of Four design patterns adhere to these principles in one form or another. The term S.O.L.I.D. comes from the initial letter of each of the five principles that were collected in the book Agile Principles, Patterns, and Practices in C# by Robert C. Martin.

Single Responsibility Principle (SRP):-The principle of SRP is closely aligned with SoC. It states that every object should only have one reason to change and a single focus of responsibility. By adhering to this principle, you avoid the problem of monolithic class design that is the software equivalent of a Swiss army knife. By having concise objects, you again increase the readability and maintenance of a system.

Open-Closed Principle (OCP):- The OCP states that classes should be open for extension and closed for modification, in that you should be able to add new features and extend a class without changing its internal behavior. The principle strives to avoid breaking the existing class and other classes that depend on it, which would create a ripple effect of bugs and errors throughout your application.

Liskov Substitution Principle (LSP):-The LSP dictates that you should be able to use any derived class in place of a parent class and have it behave in the same manner without modification. This principle is in line with OCP in that it ensures that a derived class does not affect the behavior of a parent class, or, put another way, derived classes must be substitutable for their base classes.

Interface Segregation Principle (ISP):-The ISP is all about splitting the methods of a contract into groups of responsibility and assigning interfaces to these groups to prevent a client from needing to implement one large interface and a host of methods that they do not use. The purpose behind this is so that classes wanting to use the same interfaces only need to implement a specific set of methods as opposed to a monolithic interface of methods.

Dependency Inversion Principle (DIP):-The DIP is all about isolating your classes from concrete implementations and having them depend on abstract classes or interfaces. It promotes the mantra of coding to an interface rather than an implementation, which increases flexibility within a system by ensuring you are not tightly coupled to one implementation.

This was a brief introduction about Design Patterns and Design Principles. Will try to come up in details about each pattern and principle in upcoming blogs.

Thanks for reading.


No comments:

Post a Comment