The Gang of Four are the four authors of the book, "Design Patterns: Elements of Reusable Object-Oriented Software" published in 1994. In this article their twenty-three design patterns are described with links to UML diagrams, source code and real-world examples for each.
Design patterns are proven solutions to common software and real-world problems, they are aimed at Object-Oriented programming. Each pattern targets a specific real-world problem that can be used to implement code. Sometimes you may identify a pattern as you code and then can implement the patterns design as per the specification.
The idea is to understand the concepts of design patterns so that you can identify solutions in code or at the design stage, each pattern is well know and tested to solve that problem, thus it cuts down on development and testing.
However design patterns are not the be all and end all to all solutions as either choosing the wrong pattern or over complexing code can lead to issues and delay deployment, as will all coding the best principle is keep it simple.
There are 24 patterns (23 in the original book) that cover a wide range of problems that you may face, these are broken down into three topics creational, structural and behavioral, I will cover more on this later in the section.
Since the original design pattern book another set of design principles have been published by Robert C Martin in 2000, these are known as the SOLID principles which is an acronym for 5 import design priciples and I will cover this in greater detail later in this section.
Lastly I will cover the final two principles DRY and KISS are more guideline principles but are well suite for programming and many other areas of life.
The 24 design patterns are broken down into three groups (Gamma Categories after Erich Gamma one of the gang of Four), in a word, we can say Creational is about instantiation, and Structural is the blueprint, and Behavioral is the pattern of the relationship among objects:
Creational | are used to create objects for a suitable class that serves as a solution for a problem. Creational patterns allow objects to be created in a system without having to identify a specific class type in the code which cuts down on code. Creational design patterns are composed of two dominant ideas. One is encapsulating knowledge about which concrete classes the system uses. Another is hiding how instances of these concrete classes are created and combined. |
Structural | are concerned with how classes and objects are composed to form large structures, they use inheritance to compose interfaces or implementations. They help you guarantee that when one of the parts changes, the entire structure does not need to change. |
Behavioral | describe interactions between objects and focus on how objects communicate with each other, they are concerned with algorithms and the assignment of responsibilities between objects. |
The below table details each pattern grouped by either Creational, Structural and Behavioral, I have also tried to add where you might use an appropriate design pattern. Don't worry if some of this is a bit cryptic I will demostrate via code each pattern. Use this table as a quick reference guide for the purpose and where to use the appropriate pattern/principle.
Creational | |||
Builder | Purpose | useful for dynamic creation of objects | |
Uses | building strings, build a person object, DOM/XML creation, streams(), etc (all about chaining member fields to build the object) | ||
Notes | use 'return this' in your code so that you can use chaining | ||
Factories | Purpose | Factory - Creates objects without exposing the instantiation logic to the client. Factory Method - Define an interface for creating an object, but let the subclasses decide which class to instantiate.The Factory method lets a class defer instantiation to subclasses Abstract Factory - provides an interface for creating families of related or dependent objects without specifying their concrete classes. |
|
Uses | Factory - Client just need a class and does not care about which concrete implementation it is getting. Factory Method - Client doesn't know what concrete classes it will be required to create at runtime, but just wants to get a class that will do the job. Abstract Factory - When your system has to create multiple families of products or you want to provide a library ofproducts without exposing the implementation details. |
||
Notes | Factory Method is used to create one product only but Abstract Factory is about creating families of related or dependent products. Abstract Factory classes are often implemented with Factory Method. Factory Methods are usually called within Template Methods. |
||
Prototype | Purpose | Create objects based upon a template of an existing objects through cloning | |
Uses | When you have to instantiate many objects (performance) its better to clone existing and change it | ||
Notes | |||
Singleton | Purpose | Only one instance of an Object can exist | |
Uses | used for logging, drivers objects, caching and thread pool | ||
Notes | - Private constructor to restrict instantiation of the class from other classes. - Private static variable of the same class that is the only instance of the class. - Public static method that returns the instance of the class, this is the global access point for outer world to get the instance of the singleton class. There are a number of ways a singleton can be implemented 1. Eager initialization 2. Static block initialization 3. Lazy Initialization 4. Thread Safe Singleton 5. Bill Pugh Singleton Implementation (inner static help class) 6. Using Reflection to destroy Singleton Pattern 7. Enum Singleton (cannot use lazy initialization but overcomes reflection issues) 8. Serialization and Singleton (deserialize issues (creates another instance of the singleton object) |
||
Structural | |||
Adapter | Purpose | Permit classes with disparate interfaces to work together by creating a common object by which they may communicate and interact, no new functionality is created. | |
Uses | convert one thing into another using an adapter in the middle, convert company tax to HRMC tax | ||
Notes | |||
Decorator | Purpose | Allows for the dynamic wrapping of objects in order to modify their existing responsibilities and behaviors, cuts down on the number of different permutations. | |
Uses | cup of milky (object), extra shot (object), hazel nutty (object), frothy milk (object) - all objects are wrapped one inside the other | ||
Notes | - Bridge you decouple abstraction from implementation by wrapping the object implemented with a class that doesn't necessarily share the same interface of the object. - Decorator modify existing behaviour by wrapping the object implemented with a class that inherits the same interface as the object implemented, so it has the same behaviours. |
||
Facade | Purpose | Supplies a single interface to a set of interfaces within a system | |
Uses | use when you have a complex system to simplify things, for example to watch a movie it will make popcorn, dim lights, pull curtains, turn on sound system, put movie on. | ||
Notes | |||
Flyweight | Purpose | The reuse of many fine grained objects, making the utilization of large numbers of objects more efficient, try to reduce memory footprint by reuse. | |
Uses | Many similar objects are used and the storage cost is high (use caching, use arrays to hold different data in an object but use the same object) | ||
Notes | |||
Proxy | Purpose | Allow access control by acting as a pass through entity or a placeholder object. | |
Uses | Security access control, remote invocation service (RMI) | ||
Notes | There are a number of different proxy types - A remote proxy is responsible for encoding a request and its arguments and for sending (and retrieving) the request (and the response) to the real object. - A virtual proxy may cache additional information about the real subject so that it can postpone the access to it. - A protection proxy checks whether the caller has sufficient access permissions for perform a request. - A Property proxy ?? - A Dynamic proxy used for logging for example |
||
Behavioral | |||
Chain Of Responsibility | Purpose | Gives more than one object an opportunity to handle a request by linking receiving objects together (chain), any object can break he chain. | |
Uses | Exception handling, filtering, security authentication (check users roles, credentials, access, etc) | ||
Notes | |||
Command | Purpose | Use an Object that represents an operation (encapsulates action/s - execute method) that can be rolled back (undo), can also be used for callbacks | |
Uses | Recording of history and can be used in call backs, thread queues/pools - decouples thread from the command object action, undoing actions, recording history, GUI buttons | ||
Notes | |||
Interpreter | Purpose | Textual input (String) needs to be processed (turned into OOP structures), turn grammar into actions | |
Uses | Interpreters (Perl, Ruby, Bash Shell), turn text formula into actual calculation formula (Matlab for example) | ||
Notes | |||
Observer | Purpose | Lets one or more objects be notified of state change in other objects within the system | |
Uses | Magazine publishing, Facebook notifications, Software updates (any thing with publish and subscribe) | ||
Notes | |||
State | Purpose | Changes in state can be explicit or in response to event (Observer Pattern), Depending on your state machine you go from one state to another | |
Uses | Gumball Machine, Jukebox, Traffic lights, Kettle (on/off), Record Player, etc | ||
Notes | |||
Strategy | Purpose | System behavior partially specified at RUNTIME, Many algorithms can be decomposed into higher and lower level parts the high level parts can then be reused | |
Uses | Gamer figure could walk, run, swim (we don't know until he/she does it), sorting (bubble sort, brick sort, etc), output text (could be XML, JSON, HTML) | ||
Notes | |||
Template Method | Purpose | Identifies the framework of an algorithm, allowing implementing classes to define the actual behavior, the class is normally abstract | |
Uses | Spring data access, game structure template, computer base template (add cpu, add memory, etc) | ||
Notes | Can be confused with the strategy class, Strategy pattern defines a family of algorithms and makes them interchangeable. Client code can use different algorithms since the algorithms are encapsulated. Template method defines the outline of an algorithm and lets subclasses part of the algorithm's implementation. So you can have different implementations of an algorithms steps but retain the algorithm's structure |
Solid principles are coding standards that all developers should know about as they are concepts for developing software in a preper way to avoid a bad design, so the code is more maintainable, understandable and flexible. The 5 concepts are the following:
I have covered the Solid Principles in another section
The DRY and KISS principles cover all walks of life and fit well with programming as well
The DRY principle is stated as 'Every piece of knowledge or logic must have a single, unambiguous representation within a system'. To avoid violating the DRY principle, divide your system into pieces. Divide your code and logic into smaller reusable units and use that code by calling it where you want. Don't write lengthy methods, but divide logic and try to use the existing piece in your method. Less code is good as it saves time and effort, is easy to maintain, and also reduces the chances of bugs.
The KISS principle is descriptive to keep the code simple and clear, making it easy to understand. To avoid violating the KISS principle, try to write simple code. Think of many solutions for your problem, then choose the best, simplest one and transform that into your code. Whenever you find lengthy code, divide that into multiple methods. If we have some functionality written by one developer and it was written with messy code, and if we ask for another developer to make modifications in that code, then first, they have to understand the code. Obviously, if the code is written simply, then there will not be any difficulty in understanding that code, and also will be easy to modify.