What is a Design Pattern?
A design pattern is a repeatable solution to a software engineering problem. Unlike most program-specific solutions, design patterns are used in many programs. Design patterns are not considered finished products; rather, they are templates that can be applied to multiple situations and can be improved over time, making a very robust software engineering tool. Because development speed is increased when using a proven prototype, developers using design pattern templates can improve coding efficiency and final product readability.
Design patterns are language-neutral, so they can be applied to any language that supports object orientation.
What does the pattern consist of?
Most patterns are described very formally so people can reproduce them in many contexts. Here are the sections that are usually present in a pattern description:
- Intent of the pattern briefly describes both the problem and the solution.
- Motivation further explains the problem and the solution the pattern makes possible.
- Structure of classes shows each part of the pattern and how they are related.
- Code example in one of the popular programming languages makes it easier to grasp the idea behind the pattern.
Some pattern catalogs list other useful details, such as the applicability of the pattern, implementation steps, and relations with other patterns.
You can’t just find a pattern and copy it into your program, the way you can with off-the-shelf functions or libraries. The pattern is not a specific piece of code, but a general concept for solving a particular problem. You can follow the pattern details and implement a solution that suits the realities of your own program.
Patterns are often confused with algorithms because both concepts describe typical solutions to some known problems. While an algorithm always defines a clear set of actions that can achieve some goal, a pattern is a more high-level description of a solution. The code of the same pattern applied to two different programs may be different.
An analogy to an algorithm is a cooking recipe: both have clear steps to achieve a goal. On the other hand, a pattern is more like a blueprint: you can see what the result and its features are, but the exact order of implementation is up to you.
What Design Pattern is Not
Design Patterns are not analysis patterns, are not descriptions of common structures like linked lists, nor are they detailed application or framework designs. Design Patterns are "descriptions of communicating objects and classes that are customized to solve a general design problem in a particular context." -- Gamma et al.
Good design patterns help make your software more flexible and reusable.
The History of Design Pattern
Design patterns date back to the late 1970s with the publication of A Pattern Language: Towns, Buildings, Construction by architect Christopher Alexander and a few others. This book introduced design patterns in an architectural context, presenting 253 patterns that collectively formed what the authors called a pattern language.
The concept of a pattern language subsequently emerged in Donald Norman's and Stephen Draper's User Centered System Design, which was published in 1986. This book suggested the application of pattern languages to interaction design, which is the practice of designing interactive digital products, environments, systems, and services for human use.
Meanwhile, Kent Beck and Ward Cunningham had begun to study patterns and their applicability to software design. In 1987, they used a series of design patterns to assist Tektronix's Semiconductor Test Systems Group, which was having trouble finishing a design project. Beck and Cunningham followed Alexander's advice for user-centered design (letting representatives of the project's users determine the design outcome) while also providing them with some design patterns to make the job easier.
Erich Gamma also realized the importance of recurring design patterns while working on his Ph.D. thesis. He believed that design patterns could facilitate the task of writing reusable object-oriented software, and pondered how to document and communicate them effectively. Prior to the 1991 European Conference on Object-Oriented Programming, Gamma and Richard Helm started to catalog patterns.
At an OOPSLA workshop held in 1991, Gamma and Helm were joined by Ralph Johnson and John Vlissides. This Gang of Four (GoF), as they subsequently were known, went on to write the popular Design Patterns: Elements of Reusable Object-Oriented Software, which documents 23 design patterns in three categories.
Modern Evolution of Design Patterns
Design patterns have continued to evolve since the original GoF book, especially as software developers have confronted new challenges related to changing hardware and application requirements.
In 1994, a U.S.-based non-profit organization known as the Hillside Group inaugurated Pattern Languages of Programs, a group of annual conferences whose aim is to develop and refine the art of software design patterns. These ongoing conferences have yielded many examples of domain-specific design patterns. For example, design patterns in a concurrency context.
In 1998 Mark Grand released Patterns in Java. This book included design patterns not found in the GoF book, including concurrency patterns. Grand also used the Unified Modeling Language (UML) to describe design patterns and their solutions. The book's examples were expressed and described in the Java language.
Elements and Scope of Design Patterns
A design pattern is made of four elements :
- Name - one or two words that describe the pattern
- Problem description - describes when to use the given pattern
- Solution - abstract description of classes, objects, and their relations in the pattern
- Consequences - pros and cons of using the pattern
An important thing that separates design patterns is the scope which is divided into:
- Class-scope - when the pattern is categorized as class-scope, it means that its goals are achieved at the compile time using inheritance
- Object-scope - when the pattern is categorized as object-scope its goals are achieved through composition during the runtime
Types of Design Patterns
There are mainly three types of design patterns:
- Creational: These design patterns are all about class instantiation or object creation. These patterns can be further categorized into Class-creational patterns and object-creational patterns. While class-creation patterns use inheritance effectively in the instantiation process, object-creation patterns use delegation effectively to get the job done.
- Use case of creational design pattern-
- Suppose a developer wants to create a simple DBConnection class to connect to a database and wants to access the database at multiple locations from code, generally what the developer will do is create an instance of DBConnection class and use it for doing database operations wherever required. This results in creating multiple connections from the database as each instance of DBConnection class will have a separate connection to the database. In order to deal with it, we create DBConnection class as a singleton class, so that only one instance of DBConnection is created and a single connection is established. Because we can manage DB Connection via one instance, we can control load balance, unnecessary connections, etc.
- Suppose you want to create multiple instances of a similar kind and want to achieve loose coupling then you can go for the Factory pattern. A class implementing a factory design pattern works as a bridge between multiple classes. Consider an example of using multiple database servers like SQL Server and Oracle. If you are developing an application using SQL Server database as the back end, but in the future need to change the database to an oracle, you will need to modify all your code, so that factory design patterns maintain loose coupling and easy implementation, we should go for the factory design pattern in order to achieve loose coupling and the creation of a similar kind of object.
- Use case of creational design pattern-
Creational design patterns are the Factory Method, Abstract Factory, Builder, Singleton, Object Pool, and Prototype.
- Structural: These design patterns are about organizing different classes and objects to form larger structures and provide new functionality.
- Use Case Of Structural Design Pattern-
- When 2 interfaces are not compatible with each other and want to establish a relationship between them through an adapter it’s called an adapter design pattern. The adapter pattern converts the interface of a class into another interface or class that the client expects, i.e adapter lets classes work together that could not otherwise because of incompatibility. so in these types of incompatible scenarios, we can go for the adapter pattern.
- Use Case Of Structural Design Pattern-
Structural design patterns are Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Private Class Data, and Proxy.
- Behavioral: Behavioral patterns are about identifying common communication patterns between objects and realizing these patterns.
- Use Case of Behavioral Design Pattern-
- The template pattern defines the skeleton of an algorithm in an operation deferring some steps to sub-classes. The template method lets subclasses redefine certain steps of an algorithm without changing the algorithm structure. For example, in your project, you want the behavior of the module to be able to extend, such that we can make the module behave in new and different ways as the requirements of the application change, or to meet the needs of new applications. However, no one is allowed to make source code changes to it, i.e you can add but can’t modify the structure in those scenarios a developer can approach template design patterns.
- Use Case of Behavioral Design Pattern-
Behavioral patterns are Chain of responsibility, Command, Interpreter, Iterator, Mediator, Memento, Null Object, Observer, State, Strategy, Template method, Visitor
Uses of Design Patterns
Design patterns can speed up the development process by providing tested, proven development paradigms. Effective software design requires considering issues that may not become visible until later in the implementation. Reusing design patterns helps to prevent subtle issues that can cause major problems and improves code readability for coders and architects familiar with the patterns.
Often, people only understand how to apply certain software design techniques to certain problems. These techniques are difficult to apply to a broader range of problems. Design patterns provide general solutions, documented in a format that doesn't require specifics tied to a particular problem.
In addition, patterns allow developers to communicate using well-known, well-understood names for software interactions. Common design patterns can be improved over time, making them more robust than ad-hoc designs.
Structure of a Design Pattern
Design pattern documentation is highly structured. The patterns are documented from a template that identifies the information needed to understand the software problem and the solution in terms of the relationships between the classes and objects necessary to implement the solution. There is no uniform agreement within the design pattern community on how to describe a pattern template. Different authors prefer different styles for their pattern templates. Some authors prefer to be more expressive and less structured, while others prefer their pattern templates to be more precise and have high grain in structure. The template below was first described by the authors of Design Patterns, This template captures the essential information required to understand the essence of the problem and the structure of the solution. Many pattern templates have less structure than this but basically cover the same content.
The Need for Design Patterns
- They Are Proven Solutions: Because Design Patterns often uses by many developers, you can be certain that they work. And not only that, you can be certain that they were revised multiple times and optimizations were probably implemented.
- They Are Easily Reusable: Design Patterns document a reusable solution that can modify to solve multiple particular problems. As they are not tie-up to a specific problem. For example, consider the Iterator Design Pattern, it is reusable throughout STL despite container and algorithm variation. Iterators are working like glue between the container and the algorithm.
- They Are Expressive: Design Patterns can explain a large solution quite elegantly. For instance, the Visitor pattern uses to perform a new operation on a range/group of classes. And thus, the standard library adopted such a pattern with a single function i.e. std::visit algorithm. The same goes for boost::flyweight<>.
- They Ease Communication: When developers are familiar with Design Patterns, they can more easily communicate with one another about potential solutions to a given problem. If you’re working with colleagues in a team of multiple developers, agree with them about the Design Patterns, as they can help you better with a problem. Also with regard to the maintenance of software, you should follow such procedures, as you make maintenance operations faster and more efficient.
- They Prevent the Need for Refactoring Code: If an application is written with Design Patterns in mind, it is often the case that you won’t need to refactor the code later on because applying the correct Design Pattern to a given problem is already an optimal solution. If such solutions are then updated, they can seamlessly apply by any good software developer and do not cause any problems.
- They Lower the Size of the Codebase: Because Design Patterns are usually elegant and optimal solutions, they usually require less code than other solutions. This does not always have to be the case as many developers write more code to improve understanding.
Design Pattern Pros and Cons
The option to use tried and tested solutions can save you time and money. Development teams do not have to constantly reinvent the wheel to solve subtasks in a program procedure that has already been solved multiple times before. The individual patterns are usually named using common design vocabulary. This simplifies discussions between developers as well as communication with the user of the future solution. The software’s documentation is also simplified if you use building blocks that have already been documented. These advantages also hold true for the maintenance and further development of a program.
Using design patterns requires extensive knowledge. Having design patterns available can also lead to people believing that apparently all problems can be solved using existing design patterns. In short, this can limit creativity and the desire to find new (better) solutions.
It has been observed that design patterns may just be a sign that some features are missing in a given programming language (Java or C++ for instance). Peter Norvig demonstrates that 16 out of the 23 patterns in the Design Patterns book (which is primarily focused on C++) are simplified or eliminated (via direct language support) in Lisp or Dylan. Related observations were made by Hannemann and Kiczales who implemented several of the 23 design patterns using an aspect-oriented programming language (AspectJ) and showed that code-level dependencies were removed from the implementations of 17 of the 23 design patterns and that aspect-oriented programming could simplify the implementations of design patterns. See also Paul Graham's essay "Revenge of the Nerds". Inappropriate use of patterns may unnecessarily increase complexity.
- Definition - What does Design Pattern Mean?
- What does the pattern consist of?
- What Design Pattern is Not
- The History of Design Pattern
- What are the Elements and Scope of Design Patterns?
- What are the Different Types of Design Patterns
- Uses of Design Patterns
- What is the Structure of a Design Pattern?
- Why Do We Need Design Patterns?
- The pros and cons of using design patterns
- Criticism of Design Pattern Wikipedia