This is the 1st post in a series on design patterns.
“A design that doesn’t take change into account risks major redesign in the future.” ― Erich Gamma
In object-oriented design, patterns are typical solutions to common problems. When a solution appears time and time again in a variety of projects, someone eventually names it and describes it in detail. That’s how patterns are discovered.
Patterns are like pre-made blueprints that you can customize to solve recurring problems in your code. A pattern is not a specific piece of code but a general concept that solves a particular problem. You can follow the pattern details and implement a solution that suits your own program.
In 1995, Erich Gamma, John Vlissides, Ralph Johnson, and Richard Helm published the book “Design Patterns: Elements of Reusable Object-Oriented Software”, in which they applied design patterns to programming. Due to its long name, it came to be known as the GOF book or the books by the gang of four.
Why learn these design patterns
It’s possible to be a programmer for many years without knowing about a single pattern. That’s what many people do. Even then, you might be implementing some patterns without even knowing it.
A design pattern is a set of tried and tested solutions to common software design problems. Even if you never encounter these problems, learning patterns is still valuable, as it teaches you how to solve a variety of problems using the principles of object-oriented design.
By providing shorthand terminology, design patterns also facilitate communication among team members.
Classification of design patterns
Design patterns fall into three main categories:
- Creational patterns — They provide object creation mechanisms that increase flexibility and reuse of existing code.
- Structural patterns — They explain how to assemble objects and classes into larger structures while keeping the structures flexible and efficient.
- Behavioral patterns — They take care of effective communication and the assignment of responsibilities between objects.
Creational Design Patterns
Creational patterns provide various object creation mechanisms, which increase flexibility and reuse of the existing code.
There are 5 creational design patterns defined in the GoF design patterns:
- Singleton — A singleton is a creational design pattern that ensures a class has only one instance and provides a global access point to this instance.
- Factory — The factory method is a creational design pattern that provides an interface for creating objects in a superclass while allowing subclasses to change what type of object is created.
- Abstract Factory — The abstract factory is a creational design pattern that allows you to produce classes of related objects without specifying their concrete classes.
- Builder — A builder is a creational design pattern that lets you construct complex objects step by step. You can create different types and representations of an object using the same construction code.
- Prototype — A prototype is a creational design pattern that lets you copy existing objects without making your code dependent on their classes.
Structural Design Patterns
A structural design pattern explains how to assemble objects and classes into larger structures while keeping them flexible and efficient.
There are 7 structural design patterns defined in the GoF design patterns:
- Adapter — Adapter is a structural design pattern that allows objects with incompatible interfaces to communicate.
- Composite — Composite is a structural design pattern that let you compose objects into tree structures and then work with those structures as if they were individual objects.
- Proxy — Proxy is a structural design pattern that allows you to provide a placeholder or substitute for another object. Using a proxy, you can control access to the original object, allowing you to do something before or after the request is delivered to the original object.
- Flyweight — With flyweight, you can fit more objects into RAM by sharing common parts of the state between multiple objects rather than keeping all of the data in each of them.
- Facade — A facade is a design pattern that provides a simplified interface to a library, a framework, or any other set of classes.
- Bridge — Bridge is a design pattern that allows you to split a large class or a set of closely related classes into two separate hierarchies — abstraction and implementation — that can be developed independently.
- Decorator — Using the decorator design pattern, you can attach new behaviors to objects by placing them inside special wrapper objects that contain the new behaviors.
Behavioral Design Patterns
Behavioral patterns involve algorithms and the assignment of responsibilities between objects.
There are 11 behavioral design patterns defined in the GoF design patterns:
- Template method — A template method is a behavioral design pattern that defines the skeleton of an algorithm in the superclass, but allows subclasses to override specific steps without modifying its structure.
- Mediator — Using the mediator, you can reduce chaotic dependencies between objects. The pattern restricts direct communication between the objects and forces them to collaborate only through a mediator.
- Chain of Responsibility — Chains of responsibility allow you to pass requests along a chain of handlers. Upon receiving a request, each handler decides whether to process the request or to pass it on to the next handler in the chain.
- Observer — The observer pattern allows you to define a mechanism to notify multiple objects about events that occur to the object they are observing.
- Strategy — Using the strategy, you can define a family of algorithms, put them into different classes, and make their objects interchangeable.
- Command — Command is a behavioral design pattern that turns requests into stand-alone objects containing all information about them. With this transformation, you can parameterize methods with various requests, delay or queue the execution of a request, and support undoable operations.
- State — As a behavioral design pattern, the state lets an object change its behavior when its internal state changes. It looks as if the object changed its class.
- Visitor — Using the visitor pattern, you can separate algorithms from the objects on which they operate.
- Interpreter — The interpreter is a behavioral design pattern
that defines a grammatical representation for a language and provides an interpreter to deal with this grammar.
- Iterator — A behavioral design pattern called an iterator lets you traverse elements of a collection without exposing their underlying representation.
- Memento — The memento is a behavioral design pattern that allows you to save and restore the previous state of an object without revealing its implementation details.
In future posts, we will go into detail about each of these design patterns.