Identifying Design Patterns

Matthew Chappelow
Ingeniously Simple
Published in
5 min readNov 24, 2020

An important part of being able to discuss product design and architecture is having a common language, design patterns are a part of this common language. This document seeks to help the reader to develop this common language by allowing them to match the name to the implementation.

Interior of decorative red roof truss

Patterns that are often seen defined explicitly

The following patterns are found regularly in code and will often communicate the pattern they follow in their naming.

Factory:

A method which can be called on an abstract class or interface that is able to construct and return an instance of another class based off an abstract class or implementing an interface. This allows creation of the class to be swapped out.

This is one of the most commonly found design patterns though often will be implemented as a static class thus removing one of the main benefits of this pattern.

Abstract Factory:

A collection of factory methods in a single class/interface which allows a set of related classes to be created. This is useful when the elements being created need to be created as a collection to work but can be replaced by a different collection of similar items that also need to be created as a collection to work.

Builder:

The minimal implementation of this involves only the builder itself; a class with a reference to a product object, a set of functions implementing a builder interface that can be called to add components to the product, and a function to return the product when the caller has finished adding components. Optionally a director class can be added to manage the calls to the interface functions used to construct the object when given a builder to work on. This pattern, especially with the director, is useful when the product is a complex construction with many configuration possibilities.

Fluent Builder:

A variation on the builder which requires multiple interfaces to be defined such that each completed operation returns an object implementing an interface that contains only the calls that are valid to make next in the sequence.

Composite:

An abstract base class or interface defining the interface for a generic component, this will define functions to add and remove elements plus the functionality all elements are expected to have. At least one component inheriting the interface that can hold some form of collection of generic components. Will likely also contain components inheriting the interface that cannot hold collections of generic components. The result of this is the ability to create a collection of elements of this type; this collection can then be used in the same way as any single element.

Decorator:

This starts with an abstract class or interface, implementing this will be all the components that could be decorated plus a base implementation, usually an abstract class, for all the decorators. The decorator base will hold a reference to a single component implementing the main interface to which requests will be forwarded. Individual decorator instances will inherit this decorator base to add some functionality to a request before or after it is forwarded on thus wrapping the original functionality. As a decorator implements the original interface these can be stacked as required.

Façade:

A class providing methods to perform some common operations with a subsystem, these methods will manage calling the parts of the subsystem in the required sequence for that use case. The façade does not hide the subsystem itself which is therefore still able to be used independently when an operation not provided by the façade is required.

Command:

A class with the sole purpose of being created with the parameters required to call another class and the method to execute that call. This encapsulates the request so it can be executed later, useful for attaching to UI controls to enact the behaviour of a button.

Iterator:

A pair of interfaces or abstract classes, one for the collection and one for the iterator. The collection interface contains only a method to return a class that implements the iterator interface. The iterator interface contains the methods required for iteration. Beyond this implementation details can vary considerably. The purpose of the iterator is to hide the navigation properties of a collection class such that the only indication that this class is a collection is the presence of the method to acquire an iterator.

Memento:

A class with only a set and a get declared publicly, the class which uses the memento class to store some or all of its state, and a class that holds on to instances of the memento class. The holding class can then restore the other to the state it was in at the point a memento was populated.

Strategy:

A class which contains a reference to one or more abstract classes. Function calls to this strategy class are then passed on to the appropriate stored classes. The class itself should not have any implementation of its own. The instances of the abstract classes are expected to be trying to accomplish approximately the same task in different ways.

Visitor:

Involves three actors. A class designed to accept visitors, to make use of this pattern this should be abstract or implement an interface and have multiple distinct implementations. One or more visitors which have a function to implement the equivalent behaviour for each of the distinct implementations of the abstract or interface. And a caller which will call the visit function on the base type passing the required visitor.

Patterns that are often seen defined implicitly

The following patterns are found occasionally in code but will not usually communicate the pattern they follow in their naming.

Prototype:

A method on an abstract class or interface that is called to return a copy of itself to the caller. The IClonable<T> interface provides the standard for this in C#.

Singleton:

A static function on a class that when called will return one of a limited number of instances of that class, most often this is limited to a single instance. This is now generally considered to be an anti-pattern and should be avoided where possible.

Adapter:

There are a few different ways to implement this pattern depending on the features of the language you are using. Ultimately this is a piece of code that translates calls made to one interface into calls on another target interface. The differences between possible implementations are simply in how the adapter references the code it is passing requests to, usually this will be by having it passed in to the constructor though it can also be achieved with multiple inheritance or by extending the class being referenced.

Proxy:

A class implementing an interface that holds a reference to another class that also implements the same interface. This allows the proxy to be substituted in for the class it holds a reference to and to intercept calls to the interface functions and perform its own processing before deciding whether to pass on the request to the class it holds a reference to. This can be used to useful for deferring expensive operations, abstracting away permissions, or providing advanced lifecycle management functionality.

Chain of Responsibility:

Each link in the chain shares an interface with a function to handle an action and a function to pass the action on to the handle action function of the next link in the chain. Easiest to do with composites where there’s an inbuilt hierarchy to pass the actions through.

Observer:

An interface on one side to attach and detach observers and to notify all attached observers. Another interface on the other end to receive the notifications through delegates.

--

--