This article briefly documents some common design patterns in JS.

The core idea of design patterns is to encapsulate change. Whether creative, structural, or behavioral, these specific design patterns encapsulate different types of change in their own way. Creative patterns encapsulate change in the creation of objects, like factory patterns, which decouple the creation of objects. The structural pattern encapsulates the change of the combination mode between objects and aims to flexibly express the coordination and dependence relationship between objects. Behavioral patterns, on the other hand, decouple the ever-changing behavior of objects, making it safer and easier to change behavior.

The factory pattern

The factory pattern is one of the most common design patterns used to create objects. Instead of exposing the concrete logic that creates the object, we will encapsulate the logic in a function that can then be thought of as a factory. According to the degree of abstraction, factory patterns can be divided into simple factories, factory methods and abstract factories.

1. Simple factory mode

The Simple Factory pattern, also known as the static Factory pattern, allows a Factory object to create an instance of a product object class. Mainly used to create objects of the same class. Simple factories can only be used when a small number of objects are being created and the creation logic of objects is not complex.

function createBook(name, time, type) {
    var o = new Object();
    o.name = name;
    o.time = time;
    o.type = type;
    o.getName = function() {
        return this.name;
    };
    return o;
}

var book1 = createBook('js book', 2020, 'js');
var book2 = createBook('css book', 2021, 'css');
book1.getName();
book2.getName();
Copy the code

2. Factory method pattern

The Factory Method defines an interface for creating objects that subclasses decide which class to instantiate. This pattern delays instantiation of a class to subclasses. Subclasses can override interface methods to specify their own object types when they are created.

Class User {constructor(name = ", viewPage = []) {if(new.target === User) {throw new Error(' Abstract class cannot be instantiated! '); } this.name = name; this.viewPage = viewPage; } } class UserFactory extends User { constructor(name, viewPage) { super(name, viewPage) } create(role) { switch (role) { case 'superAdmin': Return new UserFactory (' super administrator '[' front page', 'address book', 'found pages',' rights management ']); break; Case 'admin': return new UserFactory(' normal user ', [' home ', 'address book ',' discover page ']); break; Case 'user': return new UserFactory(' normal user', [' home ', 'address book ',' discover page ']); break; Default: throw new Error(' superAdmin, admin, user')}}} let userFactory = new userFactory (); let superAdmin = userFactory.create('superAdmin'); let admin = userFactory.create('admin'); let user = userFactory.create('user');Copy the code

3. Abstract factory pattern

Abstract Factory pattern: Factory abstraction of a class enables its business to be used to create clusters of product classes, rather than to create instances of a particular class of products.

The simple factory pattern and the factory method pattern both generate instances directly, but the abstract factory pattern is different. The abstract factory pattern does not generate instances directly, but is used to create clusters of product classes.

function getAbstractUserFactory(type) { switch (type) { case 'wechat': return UserOfWechat; break; case 'qq': return UserOfQq; break; case 'weibo': return UserOfWeibo; break; default: Let WechatUserClass = getAbstractUserFactory('wechat'); throw new Error(' superAdmin ', admin, user'); let QqUserClass = getAbstractUserFactory('qq'); let WeiboUserClass = getAbstractUserFactory('weibo'); Let wechatUser = new WechatUserClass(' wechat xiao Li '); Let qqUser = new QqUserClass('QQ xiao Li '); Let weiboUser = new WeiboUserClass('微博小李');Copy the code

Factory mode main application scenarios: jQuery selector $, Vue asynchronous component.

4. Singleton mode

Singleton: Also known as a Singleton pattern, is an object class that is allowed to be instantiated only once.

The singleton pattern has the following characteristics:

  • Uniquely used in the system
  • Only one instance of a class (note that there can only be one instance, which must be strongly equal ===)
let Modal = (function(){ let instance; return function(name) { if (instance) { return instance; } this.name = name; return instance = this; }}) (); Modal.prototype.getName = function() {return this.name} let question = new Modal(' question box '); Let answer = new Modal(' answer box '); console.log(question === answer); // true console.log(question.getName()); // 'question box' console.log(answer.getName()); // 'question box'Copy the code

The implementation of the singleton pattern essentially creates a reference that can return an instance of an object and a method to get that instance. Ensure that references to created objects are always unique.

The singleton is mainly used in Vuex and Store in Redux.

5. Adapter mode

The interface (method or attribute) of one class (object) is converted to another interface to meet user requirements, so that interface incompatibilities between classes (object) can be solved through adapters.

Class Plug {getName() {return 'iPhone charger '; } } class Target { constructor() { this.plug = new Plug(); } getName() {return this.plug.getName() + 'adapter Type-c charging head '; } } let target = new Target(); target.getName(); // iPhone charging head adapter to Type-C charging headCopy the code

Advantages:

  • You can have any two unrelated classes run together.
  • Improved class reuse.
  • Adapt objects, adapt libraries, adapt data

Disadvantages:

  • The creation of additional objects, not directly called, has some overhead (and unlike the proxy pattern, performance is optimized at some function points)
  • If the adapter pattern is not necessary, consider refactoring, and if so, document as well as possible

Scene:

  • Integrate third-party SDKS
  • Encapsulate old interface
  • The computed vue

6. Proxy mode

Proxy mode: Since one object cannot directly reference another object, Proxy objects are used to mediate between the two objects.

Generally speaking, the proxy mode should highlight the meaning of “agent”. This mode scenario requires three roles, namely consumer, target object and agent. The purpose of the consumer is to directly access the target object, but not directly, but through the agent first. So the mode is very much like the star agent scenario. Its characteristics are as follows:

  • The user has no access to the target object;
  • Add agent in the middle, do authorization and control through agent.
class ReadImg { constructor(fileName) { this.fileName = fileName; this.loadFromDisk(); } display() { console.log('display... ' + this.fileName); } loadFromDisk() { console.log('loading... ' + this.fileName); } } class ProxyImg { constructor(fileName) { this.readImg = new ReadImg(fileName) } display() { this.readImg.display(); } } let proxyImg = new ProxyImg('1.png'); proxyImg.display();Copy the code

The main application scenarios of the proxy mode are:

  • HTML element event broker
  • $.proxy
  • ES6 Proxy

7. Iterator pattern

Iterator pattern: Elements inside an aggregate object can be accessed sequentially without exposing the internal structure of the object.

Application scenarios of iterator mode:

  • Array.prototype.forEach
  • JQuery $. In the each ()
  • ES6 Iterator

8. Strategic mode

Strategy pattern: Encapsulate a defined set of algorithms to replace each other. The encapsulation algorithm is independent and does not change with the client.

Policy mode usage scenario: Scenario example

  • If there are many classes in a system that are distinguished only by their behavior, then using the policy pattern dynamically allows an object to choose one behavior among many behaviors.
  • A system needs to dynamically choose one of several algorithms.
  • Form validation

9. Observer mode

Observer: Also known as the publisk-subscribe or messaging pattern, it defines a one-to-many dependency between objects. When an object’s state changes, all dependent objects are notified.

What observer mode does:

  • It is widely used in asynchronous programming as an alternative to passing callback functions.
  • An object no longer explicitly calls an interface of another object. Having two objects loosely coupled to each other, while not knowing the details of each other, does not prevent them from communicating with each other.

Two advantages: decoupling in time and decoupling between objects.

Application scenarios of observer mode:

  • DOM events

  • Custom Events

  • EventEmitter event listener in Node.js

  • Vue responsive

  • Vue’s Watch lifecycle hook

Decorator mode

Decorator pattern (Decocator) : Without changing the original object, extend it by wrapping it (adding attributes or methods) so that the original object can meet the user’s more complex needs.

Therefore, it has two main characteristics:

  • Add new functionality to the object;
  • Without changing its original structure and function, that is, the original function will continue to be used, and the scene will not change.

Advantages:

  • The decorator class and the decorator class are decoupled from each other by caring only about their core business.
  • Convenient dynamic extension functionality, and provides more flexibility than inheritance.
Class Circle {draw() {console.log(' draw a Circle '); } } class Decorator { constructor(circle) { this.circle = circle; } draw() { this.circle.draw(); this.setRedBorder(circle); } setRedBorder(circle) {console.log(' draw a red border '); } } let circle = new Circle(); let decorator = new Decorator(circle); decorator.draw(); // Draw a circle with a red borderCopy the code

11. State mode

State: When the internal State of an object changes, it causes its behavior to change, which appears to change the object.

12. Command mode

Command pattern: The request and implementation are decoupled and encapsulated as separate objects to parameterize the implementations of different request heap clients.

Bridge mode

Bridge pattern: The system is decoupled while varying along multiple dimensions without increasing its complexity.

14. Combination mode

Composite: Also known as the partial-whole pattern, objects are grouped into a tree structure to represent a hierarchy of partial-whole parts. The composite pattern makes the use of single objects and composite objects consistent.

15. Enjoy yuan mode

Flyweight: The use of sharing technology effectively supports a large number of fine-grained objects, avoiding the unnecessary overhead of having the same content between objects.

16. Template method pattern

Template Method: Defines a skeleton of the operating algorithm in the parent class, while deferring some of the implementation steps to the child class so that the child class can redefine some of the implementation steps in the algorithm without changing the structure of the parent class.

17. Chain of responsibility model

Chain of Responsibility pattern: solve the coupling between the sender and the receiver of the request, decompose the request process through multiple object pairs in the Chain of Responsibility, and realize the transfer of the request between multiple objects until the last object completes the processing of the request.

18. The intermediary model

Mediator: Encapsulates the interaction between a series of objects through a Mediator object, making them no longer refer to each other and reducing their coupling. Sometimes a mediator object can also change the interaction between objects.

Refer to the content

JavaScript Design Patterns and Practices — Factory patterns

Dive into JavaScript design patterns, and you’ll have a theoretical basis for optimizing your code

JavaScript Design Mode ES6 (23 types)

JavaScript Design Patterns

JavaScript Design Patterns and Development Practices