GoF design patterns in pure functional light
These are the 23 original GoF design patterns, grouped in three categories by the main purpose.
- Abstract Factory pattern groups object factories that have a common theme
- Builder pattern constructs complex objects by separating construction and representation
- Factory Method pattern creates objects without specifying the exact class to create
- Prototype pattern creates objects by cloning an existing object
- Singleton pattern restricts object creation for a class to only one instance
- Adapter allows classes with incompatible interfaces to work together by wrapping its own interface around that of an already existing class
- Bridge decouples an abstraction from its implementation so that the two can vary independently
- Composite composes zero-or-more similar objects so that they can be manipulated as one object
- Decorator dynamically adds/overrides behaviour in an existing method of an object
- Facade provides a simplified interface to a large body of code
- Flyweight reduces the cost of creating and manipulating a large number of similar objects
- Proxy provides a placeholder for another object to control access, reduce cost, and reduce complexity
- Chain of Responsibility delegates commands to a chain of processing objects
- Command creates objects which encapsulate actions and parameters
- Interpreter implements a specialized language
- Iterator accesses the elements of an object sequentially without exposing its underlying representation
- Mediator allows loose coupling between classes by being the only class that has detailed knowledge of their methods
- Memento provides the ability to restore an object to its previous state (undo)
- Observer is a publish/subscribe pattern which allows a number of observer objects to see an event
- State allows an object to alter its behavior when its internal state changes
- Strategy allows one of a family of algorithms to be selected on-the-fly at runtime
- Template Method defines the skeleton of an algorithm as an abstract class, allowing its subclasses to provide concrete behavior
- Visitor separates an algorithm from an object structure by moving the hierarchy of methods into one object
Following analysis is presented from all the patterns.
Some design patterns are very trivial to implement in functional programming. For example Template Method is just a function which is then partially applied to do something usefull. On the other hand Iterator is way more complex to implement and understand.
How well the intention of the design pattern fits to pure functional programming. Since the original GoF design patterns are found from object-oriented programming, it may be the case that some of them do not fit well to functional programming.
For example Observer design pattern is used to notify changes in the subject object. Since immutability is one of the key concepts in functional programming, there is not much use for the design pattern.
On the otherhand Template Method is what functional programming is all about. Combining simple functions to perform some complicated tasks. Fit of this pattern is natural.
| Value | Meaning |
|---|---|
| None | Pattern cannot be applied at all to functional programming |
| Artifical | Pattern can be applied, but it is not good functional design |
| Natural | Pattern fits fluently to functional programming |
How complicated the functional version of the design pattern is. Some design patterns are reduced to negligible in pure functional form.
For example Strategy is set of functions having the same signature and conceptually performing the same task. This kind of design pattern is trivial in functional programming.
On the other hand some design patterns have more complex structure or require more advanced techniques, like typeclasses and lenses. These patterns are classified to be more complex.
| Value | Meaning |
|---|---|
| Trivial | Pattern uses only the very basic techniques (partial application, composition etc) |
| Medium | Pattern uses more advanced techniques (typeclasse, statically resolved type parameters etc) |
| Complex | Pettern uses advanced functional tecniques (lenses, zippers, memoization, infinite lazyness) |
Short summary of the all above things with optional notes and remarks.
If answer to the "applicability" was 'Yes', then a F# example is presented. Some of the examples are also implemented in Haskell. In these cases it is examined if typeclasses or other features missing from F# do any difference.