Design Patterns in Typescript
Page content
- A design pattern offers a widely applicable and reusable solution for addressing common problems in software design.
- It illustrates how classes or objects interact and relate to each other.
- It is programming language-independent, so it represents thinking.
- We should understand the intention and use of each pattern.
1. Creational patterns
- They instantiate classes using inheritance, or create objects using delegation.
- How objects are created…
1.1 Abstract factory
- Create entire product families without specifying their concrete classes
- It takes over the responsibility of creating objects.
1.2 Factory
- Create product objects without specifying their concrete classes
- It takes over the responsibility of creating objects.
1.3 Builder
- Construct complex objects step-by-step
- It manages the creation process.
- It has four parts:
- Product is the final complex object which we obtain in the end.
- Builder (Interface) abstracts the building process.
- Builder (Concrete) implements interface and builds the product. The more different products we want to send to the assembly line, the more builders we have.
- Director communicates with the client. It has a construction method that captures the right builder objects.
1.4 Prototype
- Create a new object by copying an existing one and allowing us to modify the newly created object. Use:
- if an object initialisation is costly.
- when creating similar multiple objects with different values.
- when you want to reduce subclassing.
- when reating immutable objects, since each clone is a separate instance.
clone
orcopy
methods can reveal the prototype design pattern.
1.5 Singleton
- Ensure that a class has only one instance, while providing a global access point to this instance
class Setting {
constructor(
public readonly name: string,
public readonly value: number | string
) { }
}
class Settings {
private settings: Setting[] = [];
private static instance: Settings | null = null;
private constructor() {}
static getInstance() {
if (!Settings.instance) {
Settings.instance = new Settings();
}
return Settings.instance;
}
addSetting(setting: Setting) {
this.settings.push(setting);
}
getSettings() {
return this.settings;
}
}
const settingsSingleton = Settings.getInstance();
settingsSingleton.addSetting(new Setting("Volume", 20));
console.log(settingsSingleton.getSettings());
2. Structural patterns
- They create larger structures that offer additional features and capabilities by arranging different classes and objects.
- How objects relate to each other…
2.1 Adapter
- Allow objects with incompatible interfaces to collaborate
2.2 Bridge
- Split a large class or a set of closely related classes into two separate hierarchies-abstraction and implementation- which can be developed independently of each other
2.3 Composite
- Compose objects into tree structures and then work with these structures as if they were individual objects
2.4 Decorator
- Attach new behaviours to objects by placing these objects inside special wrapper objects that contain the behaviours
2.5 Facade
- Provide a simplified interface to a library, a framework, or any other complex set of classes
2.6 Flyweight
- Fit more objects into the available amount of RAM by sharing common parts of state between multiple objects instead of keeping all of the data in each object
2.7 Proxy
- Provide a substitute or placeholder for another object
3. Behavioral patterns
- They recognise shared communication patterns among objects and implement them.
- How objects communicate to each other…
3.1 Chain of responsibility
- Pass requests along a chain of handlers
3.2 Command
- Turn a request into a stand-alone object that contains all information about the request
3.3 Iterator
- Traverse elements of a collection without exposing its underlying representation
3.4 Mediator
- Reduce chaotic dependencies between objects
- It restricts direct communication between the objects and forces them to collaborate only via a mediator object.
3.5 Memento
- Save and restore the previous state of an object without revealing the details of its implementation
3.6 Observer
- Define a subscription mechanism to notify multiple objects about any events that happen to the object they’re observing
3.7 State
- Alter an object behaviour when its internal state changes
3.8 Strategy
- Define a family of algorithms, put each of them into a separate class, and make their objects interchangeable
3.9 Template
- Define the skeleton of an algorithm in the superclass but lets subclasses override specific steps of the algorithm without changing its structure
3.10 Visitor
- Separate algorithms from the objects on which they operate