Some time ago, I read a free book covering some of the design patterns in JavaScript. I found myself referring back to it from time to time. Here is the notes I took listed here to make a quick reference cheat sheet:
The Factory Pattern
Problem to solve:
Often a class or object will contain other objects within it. The logic of creating objects lives inside the parent object and creates a dependency between the child class and parent class
Simple Factory Pattern:
Description:
Uses a separate class (often a singleton) to create instances
Example:
CarFactory::createCar(model) => Car
Complex Factory Pattern:
Description:
Uses subclasses to decide what concrete class to instantiate as a member object.
Example:
AbstractBaseFactory::createCar(model)
AWDFactory::createCar(model) => awdModelCar
SedanFactory::createCar(model) => sedanModelCar
The Bridge Pattern
Problem to solve:
decouple an abstraction from its implementation so that the two can vary independently.
Example 1: Event Handler
getBeerById(id, callback)
addEvent(element, ‘click’, function(e){ getBeerById(e.id, cb) );
instead of
addEvent(element, ‘click’, getBeerById(e) { … }); //couples the implementation with event
Example 2: Privileged methods as a bridge to gain access to the private variable
var public = function() {
var secret = 3;
this.privilegedGetter = function() {
return secret;
};
};
Example 3: Bridging Multiple Classes Together
var Class1 = function(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
}
var Class2 = function(d) {
this.d = d;
};
var BridgeClass = function(a, b, c, d) {
this.one = new Class1(a, b, c);
this.two = new Class2(d);
};
The Composite Pattern
Problems to solve:
To treat a collection of objects the same as you would treat any of the particular sub-objects. It organizes sub-objects into a tree structure and allows the entire tree to be traversed.
Examples:
Form validation
Forms – >validate()
Form -> validate()
Section -> validate()
Field -> validate()
Hide/Show HTML Elements
parentDiv -> hide/show
childrenDiv -> hide/show
element -> hide/show
The Facade Pattern
Problem to solve:
The facade pattern does two things:
- it simplifies the interface of a class,
- and it decouples that class from the client code that uses it.
Example: Create a function for registering event handler in all browsers
function addEvent(el, type, fn) {
if (window.addEventListener) {
el.addEventListener(type, fn, false);
}
else if (window.attachEvent) {
el.attachEvent('on' + type, fn);
}
else {
el['on' + type] = fn;
}
}
Example: As Convenient Methods
function getFullName = function (){
return firstname + ’ ‘ + lastname;
}
The Adapter Pattern
Problem to solve:
The adapter pattern allows you to adapt existing interfaces to classes that would otherwise be incompatible.
What it is
An adapter converts one interface to another; it doesn’t remove any ability or otherwise simplify the interface.
Note that Adapter class simply wraps an object and converts the arguments given into what the function expects to receive.
The Decorator Pattern
The problem to solve:
The decorator pattern is used to transparently wrap objects within another object of the same interface. This allows you to add behavior to a method and then pass the method call on to the original object. Using decorator objects is a flexible alternative to creating subclasses.
In What Ways Can a Decorator Modify Its Component?
- Adding Behavior Before/After a Method
- Replacing a Method
- Adding New Methods
The Flyweight Pattern
The problem to solve:
It’s most useful in situations where large numbers of similar objects are created, causing performance problems.
The flyweight pattern is used to reduce the number of objects you need in your applications.
How
The first step is to separate the intrinsic state (information that is required by the internal methods of a class e.g. car make/model/year/) from the extrinsic state (information that can be removed from a class and stored externally e.g. owner details).
Instantiation Using a Factory ( make sure only one object is created for each intrinsic state )
Extrinsic State Encapsulated (e.g. a collection/database/composite of owners ) in a singleton Manager (e.g. car registration manager )
Examples:
- Tooltips and Tooltip manager
- Modals and Modal manager
The Proxy Pattern
A proxy is an object that can be used to control access to another object. It implements the same interface as this other object and passes on any method invocations to it.
A proxy does not modify the method calls that are passed on to the
real subject, other than to possibly add some control code.
Example:
- A virtual proxy controls access to a real subject that is expensive to create. It will defer instantiation of its real subject until a method is called
-
A remote proxy is used to access an object in a different environment.
-
A protection proxy is used to control access to certain methods based on who the client is.
The Observer Pattern
Problem to solve:
Observe the state of an object in a program and be notified when it changes.
A observable object has three methods associated with the instance:
subscribe, unSubscribe, and fire
The Command Pattern
It provides the ability to parameterize and pass around a method call, which can then be executed whenever you need it to be.
It provides the ability to parameterize and pass around a method call, which can then be executed whenever you need it to be.
Example: Undo and Logging
The Chain of Responsibility Pattern
To decouple the sender and the receiver of a request
Example: Express Middleware