With or without your realize, your everyday code is using one or many design patterns which are going to be introduced in this post.

If you google for Design Patterns, there will be bunch of blog posts, books talk about this topic. The recommended book is the canonical Design Patterns Elements of Reusable Object-Oriented Software. Another recommended book is Code Complete: A Practical Handbook of Software Construction, Second Edition 2nd Edition.

This post I will briefly list all patterns mentioned in this book and provide a simple explanation/concrete example for each pattern


First, list of design patterns by their purpose and scope

For a better readability, I will use typescript for the sample code.
I will also try to keep the sample code as clean as possible to emphasize the pattern's purpose.

1. Factory method (another name: Virtual Constructor)

create class based on input parameter

const createAnimalClass = (kind: 'dog' | 'cat') => kind === 'dog' ? Dog : Cat
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

2. Adapter (class, another name: Wrapper)

There is an existing class, you want to use it but the interface is not compatible, thus, you need an adapter/wrapper to create compatibility.
For example

class Logger {
    writeLog(str: string){}
}
class ConsoleLogger {
    log(kind: 'warn' | 'error' | 'log', str: string){}
}
class ConsoleLoggerAdapter {
    constructor(){this.consoleLogger = new ConsoleLogger()}
    writeLog(str: string){this.consoleLogger.log('log', str)}
}

Currently, there are many locations in old code base which use interface of Logger, now you migrate your system to use ConsoleLogger but the interfaces are incompatible. ConsoleLoggerAdapter is written to wrap new ConsoleLogger and expose the interface as you want.

3. Interpreter

A class which can interpret a language and store the input string in an internal state instead of the raw input.
Consider regular expression is a language, then RegExp is an interpreter.

const regExp = new RegExp('(0|[1-9][0-9]*)')

4. Template method

Super class (parent class) defines skeleton of an operation which, the operation, includes one or more sub-operations. These sub-operations can be defined/re-defined by sub-classes. The skeleton keeps same regardless the sub-class implementation of the overwritten sub-operations.

class Buyer {
	const unitPrice = 10
    calculateTotal(amount: number){
    	return `the total is ${this.discount(amount * this.unitPrice)}`
    }
}
class Agency extends Buyer {
	discount(total: number){return total * 0.9 * 1.1} //discount and tax
}
class Guest extends Buyer {
	discount(total: number){return total * 1.1} //tax
}

5. Abstract Factory (another name: Kit)

Similar to 1. Factory method. This pattern is used to initiate an instance from a class among a family of them, based on the parameter.

const createAnimal = (kind: 'dog' | 'cat', name: string) => kind === 'dog'
  ? new Dog(name)
  : new Cat(name)

6. Builder

A class which is used to create instances of another class. However, this builder class provides many convenient methods to build the final instance step-by-step, and it remembers each method call internally to give the final or currently being built instance.

class StringBuilder {
	getString(): string
    reset(str: string): StringBuilder
    append(str: string): StringBuilder
    prepend(str: string): StringBuilder
    replace(str: string): StringBuilder
    space(str: string): StringBuilder
}
new StringBuilder().reset('hello').space().append('world').getString()

7. Prototype

Use an object keeping behaviors (methods) as a prototypical instance. Every time new object is created, the new object copies behaviors from the prototypical instance. This prototype pattern is supported native in Javascript and it brings many strength to the Javascript language itself. Object.create method takes the first parameter as prototype and instantiate new object.

class Human{name: string}
const me = Object.create(Human.prototype, {name: 'transang'})

8. Singleton

Ensure at most one instance of a class can be initiated.

let instance
const getMyClassInstance = () => instance || (instance = new MyClass())

9. Adapter (object)

Same as Adapter for class

10. Bridge (other names: Handle, Body)

Bridge design pattern is used to separate implementation and interface. One of the most application of this pattern is that it enable the implementation can be changed at runtime.
This pattern is similar but different from inheritance pattern.

class Human{
	const pet: IPet
	setPet(pet: IPet): void
	feed(amount: number){this.pet.eat(amount)}
}
interface IPet {eat(amount: number): void}
class Dog implements IPet {}
class Cat implements IPet {}

The Human class keeps responsibility as a bridge class, separates concern of the interface IPet from its implementations ( Cat and Dog).

Difference from inheritance pattern:
In inheritance pattern, you would need to fix the implementation of IPet in the Human class, which make difficulty to extend the IPet interface, or add a new implementation.

11. Composite

Composite pattern is used to represent part-whole hierarchies.

Image that you want to build a tree whose node can be a leaf or a parent of one or more children nodes. An real-life example of this tree structure is a menu with multi-level sub menus.
A left node is called individual object, while a middle node (can be the root node) composes multiple children, thus, is called composition.

Composite pattern helps treating individual objects and compositions uniformly, in order to avoid defining different classes for each. To achieve this purpose, the composite class should introduce an interface which allow the individual objects directly implementing the interface while the compositions forwards operations to their children.

class Menu { // the general object which exposes interface for both individuals and composites to follow
	draw(): void
}
class CompositeMenu { // composite object which contains and forwards operations to its children
	draw(){
    	for (const child of this.children) child.draw()
    }
}
class TextOption extends Menu { // individual object which directly implement menu operations
}
class ButtonOption extends Menu { // similar to TextOption
}

12. Decorator (another name: Wrapper)

Decorator pattern attaches additional behavior, functionality to an existing object. It is a flexible replacement for sub-classing.

Object in the above statement can be instance of a class or a class itself.

let car = new Car()
car = attachHandler(car)
car = addWheels(car)
car = fillGasoline(car)
car.start()

Another example for class decorator

class Printer {
	print(kind: 'error' | 'warning' | 'log', str: string)
}
const setPrintType = (kind: 'error' | 'warning' | 'log') => (PrinterClass: typeof Printer) => {
	class DecoratedPrinter extends PrinterClass {
    	print(str: string){super.print(kind, str)}
    }
}
const LogPrinter = setPrintType('log')(Printer)
const WarningPrinter = setPrintType('warning')(Printer)
const ErrorPrinter = setPrintType('error')(Printer)

13. Facade (or Façade)

Image from the book by FoG

Facade pattern helps your life easier by providing a simple and user-friendly API hub for sub-system user without knowledge about the sub-system's internal process.

One of the best example is jQuery. It wraps DOM element and provide more user-friendly API interface and handle all DOM operations and browser compatibility internally.

$(el).css()
$(el).animate()

14. Flyweight

Flyweight pattern shares object in order to save memory or cache(memoize) object to prevent re-creation, re-calculation.

const flyweight = (intensiveCalc: (arg: any) => any) => {
	const results = new Map()
    return (arg: any) => {
    	if (results.has(arg)) return results.get(arg)
        const result = intensiveCalc(arg)
        results.set(arg, result)
        return result
    }
}

The above implementation considers intensiveCalc is a function which accepts only one argument, it also memoizes all entered parameters and returned result. Thus, it may caught memory overflow. Use it at your own risk.

15. Proxy (another name: Surrogate)

As the name suggested, proxy is a placeholder to control other object. Proxy is a very general concept, used in many other fields such as network connection, ...

class FileProxy{
	read(){
    	//check permission
        //order a system call to read file
    }
    write(){ // check permission, order a system call to write file
    }
}

The File class itself can be considered as a proxy for file object in OS. The file object in OS may be another proxy which exposes interface to connect user call and real data stored in hard disk.

16. Chain of Responsibility

Allow more handlers can handle the object. List of handlers should be able to be specified dynamically at run-time.

The syntax looks similar to decorator, but they serves different purposes. Best suite sample is the Promise object

Promise.resolve(3).then(x => x + 2).then(x => x - 3).then(console.log)

17. Command (other names: Action, Transaction)

Encapsulate a request as an object, help decoupling object which knows how to call a command, and, object which handle how to execute the command.
This pattern is also able to store list of executed commands, support undoable operations.

class Dispatcher{
	dispatch(action: IAction): void
    undo(): void
    listActions(): IAction[]
}

18. Iterator (another name: cursor)

A way to access the elements of an aggregate object (list, array, map, set, ...) without exposing the underlying representation.

const it = [1, 2, 3][Symbol.iterator]()
while (true) {
	const {value, done} = it.next()
    console.log(value)
    if (!done) break
}

19. Mediator

A bandmaster who stays in the center to encapsulate the interaction between a set of components. Member component directly communicates with the mediator, instead of talking with other components.

class Mediator {
	const boss: IHuman
    const pets: IPet[]
    const storage: IFood[]
    feedPets(){
    	//tell this.boos to take food from this.storage, then feed this.pets
    }
}

20. Memento (another name: Token)

21. Observer (other names: Dependents, Publish-Subscribe)

22. State (another name: Objects for States)

23. Strategy (another name: Policy)

24. Visitor

After the Design Patterns Elements of Reusable Object-Oriented Software book had been published, there were many new design patterns have been invented. There is the list of various patterns from wikipedia page

Software design patterns list