|
Introducing Design Patterns
Design Patterns are a solution to the complexities in Software Designs. This article provides a bird's eye view of the Creational, Structural and
Behavioral Design Patterns and their applicability.
By: Joydip Kanjilal
Date: May 22, 2008
Printer Friendly Version
Introduction
Since the invention of Object Oriented Programming, its philosophy has become exceedingly popular among the programming community
and has had a wide spread acceptance in the technology world. Although OOP has become largely popular, it has spawned some repeated
design problems with its continuous use. There was a need for rectifying these recurring problems in software designs. The need of the hour
was a solution for these common problems. The use of design patterns has been a significant improvement in Object Oriented Design (OOD)
and facilitates the design and development of high quality, maintainable software at a much faster rate and at a lower cost. Design Patterns
are the proven and best solution to the common problems and increasing complexities involved in software development life cycles. One of
the most important factors that determine the efficiency of a software design is its adaptability to change. My intent in authoring this article
is to provide the readers an overview of Design Patterns, their applicability and the common pitfalls of improper usage or application of
these design patterns in software designs.
Prerequisites
The reader should have a good background in the concepts of Object Oriented Programming and any one of the object oriented languages
(C++, Java, C#, etc) for understanding the concepts covered in this article. A prior knowledge of Unified Modeling Language (UML) is an added
advantage though it is not mandatory.
What are Design Patterns?
A Design Pattern essentially consists of a problem in a software design and a solution to the same. In Design Patterns each pattern is described
with its name, the motivation behind the pattern and its applicability. Understanding the applicability of a design pattern is of utmost
importance prior to implementing it.
According to MSDN, "A design pattern is a description of a set of interacting classes that provide a framework for a solution to a generalized
problem in a specific context or environment. In other words, a pattern suggests a solution to a particular problem or issue in object-oriented
software development. Additionally, patterns take into account design constraints and other factors that limit their applicability to the solution
in general. Together, the classes, the communication and interconnections among those classes, and the contextual specifics define a pattern
that provides a solution to any problem in object-oriented software design that presents characteristics and requirements matching those
addressed by the pattern context."
"A design pattern systematically names, motivates, and explains a general design that addresses a recurring design problem in object-oriented
systems. It describes the problem, the solution, when to apply the solution, and its consequences. It also gives implementation hints and
examples. The solution is a general arrangement of objects and classes that solve the problem. The solution is customized and implemented
to solve the problem in a particular context". -- Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard
Helm, Ralph Johnson, and John Vlissides.
Benefits of Design Patterns
The following are some of the major advantages of using Design Patterns in software development.
- Flexibility
- Adaptability to change
- Reusability
When to use Design Patterns
Design Patterns are particularly useful in one of the following scenarios.
- When the software application would change in due course of time.
- When the application contains source code that involves object creation and event notification.
When not to use Design Patterns
This section discusses the main points that can be used to evaluate whether or not to use design patterns to solve a problem context. Do not
use design patterns in any of the following situations.
- When the software being designed would not change with time.
- When the requirements of the source code of the application are unique.
If any of the above applies in the current software design, there is no need to apply design patterns in the current design and increase
unnecessary complexity in the design. The common pitfalls that are observed or rather encountered in a design when applying design
patterns to solve a problem that does not need it is discussed later in this article.
The Gang of Four (GOF) Patterns
The invention of the design patterns that we commonly use today can be attributed to the following four persons: Erich Gamma, Richard
Helm, Ralph Johnson and John Vlissides. These men invented 23 patterns in all that are commonly known as the Gang of Four patterns or the
GOF patterns. These patterns are named based on their intent and purpose and are classified in three broad categories stated below.
- Creational
- Structural
- Behavioral
Each of these groups in turn contains related sub patterns. These patterns are discussed in the sections that follow. The sub patterns under
the major three groups discussed above and their brief explanation are provided for better understanding.
Creational Patterns
The Creational Patterns deals with the best possible way of creating an object or an instance of a class. They simplify object creation and provide
a flexible approach towards object creation. The following are the sub-patterns that fall under this group.
- Abstract Factory
- Factory
- Builder
- Prototype
- Singleton
Both the Abstract Factory and the Factory pattern have the same intent. They have the same names and do the same thing. It is only the way
that they operate that is important. Both the Abstract Factory and the Factory pattern deal with the creation of an object. The difference
being that the Abstract Factory pattern uses objects to manage object creation while the Factory pattern does the same using inheritance.
The Abstract Factory pattern provides an interface for creation of a family of related objects, but without specifying their concrete classes.
The Factory pattern also provides an interface for the creation of objects, but allows the inherited classes to decide on the appropriate time of
these instantiations.
The Builder Pattern is one that isolates the construction of a complex object from its representation, thus ensuring that several different
representations can be created depending on the requirements. The Prototype Pattern allows an initialized and instantiated class to be copied
or cloned to create new instances rather than creating new instances. The Singleton Pattern indicates that there can be only one instance of
a class throughout the Application’s life cycle. A singleton class is one that can be instantiated only once in the application domain and provides
a global point of access to it.
Structural Patterns
Structural Patterns provides the flexibility to specify how objects and classes can interoperate. The following are the sub patterns that
comprise the Structural Patterns group.
- Adapter
- Facade
- Bridge
- Composite
- Decorator
- Flyweight
- Proxy
- Adapter
- Bridge
- Composite
- Decorator
- Flyweight
- Proxy
The Adapter Pattern allows different classes to inter-operate even with incompatible interfaces. The Facade Pattern depicts a single class that
represents a high level class in an entire subsystem and makes the subsystem easier to use. As an example, a Façade design pattern ensures
that we can have a class that can act as a layer between the User Interface Layer and the Business Service Layer. Thus, it acts as an agent in the
sense that it facilitates the communication between the User Interface Layer and the Business Service Layer in a typical n–tier application
design. It is to be noted here that both the Adapter and Façade design patterns can be used to change the interfaces of the classes, thus
enabling an easier communication of these classes from the User Interface Layer.
The Bridge Pattern eliminates the need of adapter classes in a sub system and decouples an object’s interface from its implementation so that
both can work independent of each other. The Composite Pattern is a design pattern that is used to compose a tree like structure of simple
and composite objects so that the clients can treat the individual objects and their compositions in a uniform manner. The Decorator Pattern
provides an alternative for sub classing to extend functionality in a sub system and adds responsibilities to objects even after construction of
the design of the system. The Flyweight Pattern is a fine-grained instance used for efficient sharing. The Proxy Pattern shows an object
representing another object and, like the Adapter Design Pattern, it acts as a layer between the client or the consumer application and the
actual object.
Behavioral Patterns
Behavioral patterns help you define a structure for inter-object communication between objects in your system. This design pattern is typically
used to monitor the messages that are transmitted when the objects communicate in a system. The following are the sub patterns under
Behavioral Patterns.
- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
The Chain of Responsibility Pattern is one that details a way of passing a request between a chain of objects. The Command Pattern encapsulates
a command request as an object. The Interpreter Pattern is a way to include language elements in a program. The Iterator Pattern sequentially
accesses the elements of a collection. The Mediator Pattern defines simplified communication between classes. The Memento Pattern captures
and restores an object's internal state. The Observer Pattern is a design pattern that provides a way of notifying a change to a number of its
dependant classes. Therefore, when one object changes its state, so do all its dependant objects in the sub system. The State Pattern is a
design pattern that changes an object's behavior when the internal state of the object changes. The Strategy Pattern is used to encapsulate a
family of algorithms inside a class and use them interchangeably and independent of the client application that use the same. The Template
Method Pattern is a design pattern that is used to provide a template of an algorithm and defers some of the steps of the algorithm to the
subclasses. The Visitor Pattern is one that is used to define a new operation to a class without a change.
A Word of Caution
It is agreed that design patterns can solve complexities and problems in software design phases, but improper applicability of Design Patterns
can lead to bad designs that can facilitate software design errors. Be very careful when using or applying design patterns. Do not use a pattern
to solve a problem that does not need it. Do not simply ornament software design using a design pattern when it is not at all required in that
context. Think twice before you decide to use them in your design. Understand the scope of the problem context and then search for a design
pattern that best fits in that context to solve the problem. Further, one should have an excellent understanding of the scope and applicability
of each design pattern before using it. Analyze the problem carefully, consider all options and apply the appropriate design pattern to solve
the problem. What I personally feel is that we should only implement a design pattern in our software design provided we have sufficient
knowledge of its applicability and scope. At the same time, we should be able to analyze the problem context and judge the applicability of
the correct design pattern (if it is required at all) as a solution to the problem in question. It is quite unnecessary and not wanted of a software
architect to implement a design pattern in a problem domain and increase complexity when it can be solved without using one.
References
Design Patterns (MSDN)
Gang of Four Design Patterns
Conclusion
I have provided a brief introduction to the all three categories of the Gang of Four Design Patterns in this article. The reader should be well
aware of when to use which pattern in designing the software. Recognizing the feature and benefit of a particular pattern is of utmost importance
when implementing it. The best advantage that can be gained from using these patterns is by applying the right type of pattern at the right place
in the design. Stay tuned for more articles in which I would like to provide a detailed know-how on each and every pattern with sample code
examples in each case for better understanding of a design pattern, its intent and applicability. I welcome your comments and suggestions.
Happy reading!
|