G2Labs Grzegorz Grzęda
Design patterns intro
April 27, 2023
What binds a society of professionals, are:
- line of conduct,
- common principles,
- pattern for ways to behave, create,
- legal bodies recognizing members of that society,
- …
We, the Coders share at least the first three of those commonalities. There is The Scribes Oath. There are the SOLID principles, KISS, and there are Design Patterns.
What are Design Patterns?
Design Patterns (DPs)are general, repeatable solutions to commonly occurring problems in software design. This means, that DPs don’t deliver precise answers to certain problems, but give hints and clues in which way direct the workload to achieve optimal or near-optimal results.
The origin of Design Patterns
can be traced to
the Gang of Four (GoF):
- Erich Gamma
- Richard Helm
- Ralph Jonson
- John Vlissides
In 1994, they published a book Design Patterns: Elements of Reusable Object-Oriented Software
. They were the
first to collect common ideas about writing software properly. Although, the first traces of interest in
software architecture dates way back to the late ‘70 and ‘80.
IRL example
Lets discuss an example from IRL architecture. If there is a road which needs to go across a e.g. river, we instinctively know, that we need a bridge to provide certain features to this project. We need:
- pillars,
- spans,
- some kind of road suspension.
- the land to be modeled around the terminals of the bridge in a way, so that driving through will be smooth and seamless.
That was the general idea. We don’t know:
- what precise type of the bridge we need?
- how wide is the river?
- what kind of transport will move through the bridge (cars, trains, walkers?)?
- what weather conditions are during each season?
- what budget do we have?
- …
Those were specific requirements we don’t know (yet) the answers to. Although we know, that at the end, there is a bridge to build.
Why use them?
DPs are handy, because they answer questions on how to arrange the:
- behavior,
- internals,
- communication between,
- hierarchy
of classes and object in certain situations.
Why not use them?
When DPs were cataloged, in 1994, some saw them as ‘workarounds for missing features in C++’. Especially, functional languages (Lisp, Clojure) have the design pattern spirit
embedded in them.
Also using DPs for sake of DPs is pointless. Your application stops delivering use cases and starts delivering DPs to the world. It may be a nice picture, but useless in the end.
Blindly following DPs in each and every spot of the project may lead to huge inefficiencies in the way the code handles e.g. big amounts of data. Maybe a piece of assembly macros could ruin the DP structure, but sure may get the job done.
Types of patterns
That said, now we can discuss three canonical types of Design Patterns
Creational
- efficient class and object instantiationAbstract Factory
- create whole families of similar classesBuilder
- different ways to create whole packs of similar objectsFactory Method
- creates instances of derived classesPrototype
- ready to clone or copy instanceSingleton
- only single instance of a class if allowed
Structural
- class and object composition. Implementing and containing relationsAdapter
- Match objects by common interfacesBridge
- decouple representation from implementation by an abstractionComposite
- embeds a collection of objects seen as a single object of the same typeDecorator
- on runtime adds/overrides objects functionalityFacade
- a simple interface in front of a complicated structureFlyweight
- optimized creation and handling of a swarm of objectsProxy
- Buffers real objects of the rest of system. Can on runtime change the buffered object
Behavioral
- enforcing communication between objects of certain classesChain of responsibility
- puts different actions in a collection and in a processing objectCommand
- encapsulates different actions behind a common interfaceInterpreter
- natural-like language parserIterator
- access sequentially objects of a collection without collection expositionMediator
- a third party handling interactions between loosely coupled objectsMemento
- undo functionalityObserver
- publish/subscribe structure, with subscribers able to react on eventsState
- captures the changes of the system in time. Module state storeStrategy
- runtime swap of algorithms thanks to interfacesTemplate method
- abstractly defined algorithm skeleton with parts pushed to a subclassVisitor
- single access object handles algorithms over other object collection
Additional (not included in the canonical list of Design Patterns):
Object Pool
(Creational DP) - a pool of reusable components, ready to grab, without the hassle of initialization and maintenanceNull object
(Behavioral DP) - A fake implementation of an interface, in case when the given functionality is not needed
I will discuss each with you in the future. Don’t worry if you don’t understand everything right now - you will soon.
The design pattern post series will contain at least C/C++ examples.