This article is a cheat sheet of the most used design patterns and principles. This was not made to teach you. This was made to make you remember what you already understood.
Several design patterns based on the following
Hold a reference to another object. Sometimes it means the owner manages the lifetime of that object sometimes just a simple reference.
To make it flexible this reference is mad through an interface instead of a particular class.
Move to certain functionality of another class or use functionality of another class. Applicate it using the wrapper.
Factory is a class or method which has the only task to manage the creation of other classes. Th benefit of it is that different classes don’t have to take care of the classes. Factory usually provides objects through interface.
The interface is a structure of a class without a specific implementation. It is a contract between two objects. Specifies what methods an object can have – but does not specify the behavior. Different classes implements different behavior to the same interfaces.
GoF is the abbreviation of Gang of Four – after the four authors of one of the most fundamental design patterns book
“Provide an interface for creating families of related or dependent objects without specifying their concrete classes.”
Client uses a factory (referencing Abstract Factory) to create instances of different classes. Define an interface/class which declares the methods used by the client and add different implementation of it by overriding the creation methods. This way the client can build products with the same structure using the factory by calling the appropriate method.
Abstract Factory is often implemented using Template Methods or Prototype.
“Separate the construction of a complex object from its representation so that the same construction process can create different representations”
Director class sets up a complex object by calling elementary methods defined in the Builder interface/class. Each builder subclass implements the operations in its own way so Director won’t know what parts makes
up the object and how are they assembled.
“Define an interface for creating an object, but let subclasses decide which class to instantiate”
Put a dedicated method to a class (Creator) which creates the Product. Creator also can contain other methods which is used with Product. The subclass of Creator will implement the method and create the specific Product instance.
Create new instances of a class using an existing one by cloning/copying it. Very useful, when the creation of new instances needs in runtime while the classes are referenced by an interface/base-class.
“Ensure a class only has one instance, and provide a global point of access to it”
Instance of a class can be accessed through only one method (a static/class method) and keep the only instance inside the class scope. The allocation/creation of the class instance have to be prohibited to other classes.
Be careful and do not overuse this pattern. This is one of the anti-patterns. For more information why, see here (http://andras.palfi.hu/singleton-the-anti-pattern).
Implement an interface for a class to make it compatible with another class which wants to use the first class.
Class adapter: use multiple inheritance/interface implementation to implement the new interface while subclassing the original class.
Object adapter: create a new class implementing the desired interface and encapsulate the original class holding reference to it in a member. In the interface-methods call the methods of the encapsulated class (see: delegation).
“Decouple an abstraction from its implementation so that the two can vary independently”
You have a class hierarchy which performs complicated operations. Each operation in a subclass calls the existing simpler operations referencing the operations through and interface. On the very bottom of this hierarchy there are some very simple operations. This very simple operations base to be delegated to another base class or interface so each call of the basic operations will be forwarded to another class. By subclassing this delegated class you will have complex operations using the class hierarchy while you only have to implement very simple methods. Reimplementing the basic operations in a separate class gives you a different representation of the complex hierarchy.
For example: a drawing application which draws complex shapes (rect etc.) using the drawline method on the very base. If you implement the drawline to different OS-s your complex drawing is still the same but works on different platforms.
Compose objects to hierarchies by using a base class/interface which contains the very basic mandatory operations to manage the hierarchy and perform basic operations.
You will have node classes and leaf classes. Calling a basic operation on a node will forward the same call to all its children. Hierarchy management operations will works only on node items.
Attach additional functionality to an existing component by wrapping it. For compatibility reason all the classes needs a base class/interface. All operations called on the decorator will be forwarded to the wrapped class but performing additional operations before and/or after the forwarded call.
To hide, simplify or control a complex class hierarchy create and publish a new class. Delegate all operation to the appropriate subsystem class.
Users of the facade don’t know about the subsystem classes and subsystems classes don’t know about the facade or the user classes.
Share the expensive objects between instances if there are numerous elements in a system which uses the same o almost the same classes. Do not store system-object specific states in the flyweights but pass the actual state to them on use.
A placeholder for an object to control the access to it. Wrap the original object into the proxy and forward every call to it.
remote proxy: provides a local representation of a remote object in a different address space.
virtual proxy: create the wrapped object on demand – lazy binding
protection proxy: filter the access to an object
smart pointer: reference counting and lifetime management; thread locking
Chain of Responsibility
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interactions independently. The colleague objects don’t hold reference to each other but a reference to the mediator object (through an interface or abstract class). The mediator has reference to the more important colleague objects.
Without violating encapsulation, capture and externalize an object’s internal state so that the object can be restored to this state later. Serialization/deserialization.
Define a one-to-many dependency between objects. The observers listen to the changes of observed object (subject) so that when the subject changes its state, all its observers are notified and updated automatically.
Usually the subject send out specific messages which the observers catch/handle.
Use if there is a need to change the behavior of a class in runtime. The client class holds reference to the context class which is technically a proxy. The context class holds reference to a specific state object. If the state should change the context class sets its pointer to another state class.
Encapsulate specific functionality into classes with the same interface. This way different operations or functionalities will be interchangeable.
Implement an operation using more steps. The subclasses have to add implementation of certain steps. For example opening document.
Perform different operations on an object hierarchy. Visitor base class declares VisittXXX operations for all ConcreteElements in the object hierarchy (VisitConcrete1, VisitConcrete2). The ConcreteVisitor classes overrides the VisitXXX methods to perform the necessary operations. The Element base class declares the Visit(Visitor) method which the ConcreteElement classes override and the their Visit methods will call the appropriate VisitXXX method. This way you can define and perform different operations on a hierarchy (composite, list, etc).
Non GoF Patterns:
Similar to singleton but usable for more different instances. A collection of singletons. Usually the different “singletons” can be access by a referencing key: string, enum, interface etc.
Solid is an acronym for the following principles.
- Single Responsibility Principle: a class should have only a single responsibility
- Open Closed Principle: classes should be open for extension but closed for modification
- Liskov Substitution Principle: derived classes must be substitutable for their base classes.
- Interface Segregation Principle: make fine grained interfaces that are client specific. Many client specific interfaces are better than one general purpose interface.
- Dependency Inversion Principle: depend on abstractions not on concrete implementations. There are high level and low level objects. High level uses the low level. The concept is that the high level should specify the interface which should be implemented by the low level (the writer methods of a logging interface should come from the higher level object and not specified for example by the FileWriter which contains file level attributes/properties)
Inversion of Control – IoC
Used to decouple different classes so the classes won’t reference each other but should use interfaces and will get the used instances on another way. (Belongs to the Dependency Inversion Principle)
Instead of referencing (and creating) objets of specific classes use a special class which provides the necessary classes on runtime. The service locator usually provides long live objects but also can behave like a factory (or better if it uses one). The service locator is a proper substitution of the singleton pattern.
Dependency injection – DI:
pass the dependent objects to the user class on runtime
Constructor injection: pass as a parameter of the constructor
Setter injection: pass by calling a setter method
Interface injection: interface declares a setter like logic and should override the original class.
Separation of Concerns
Other patterns, principles
Encapsulate sets of operations together with their context/used variables. Usually in the background the compiler generates a tiny class for you.
Lazy load/ Late binding
Opaque pointer/Pimpl idiom
The ability of a program to check/get information of a class in runtime so the client can make decisions and perform different operations depending on the information of the referenced class.
Type introspection + the ability to modify the structure and behavior of classes in runtime.
Model-View-Controller – MVC
Controller has reference to the View and the Model, View can have a reference to the Model,
Model-View-Presenter – MVP
Presenter has reference to the View and to the Model. The view doesn’t have reference to the model or to the Controller
Passive View – MVP PV: the view no longer responsible for updating itself from the model.
Supervising Presenter – MVP SC: view uses some form of Data Binding to populate much of the information for its fields, for complex interactions then the controller steps in.
View has reference to the Presenter (presentation model), it doesn’t know about the view. Presentation model fires events what are handled by the View.
PM with data binding.