series

  • Using JavaScript learning design patterns (1) | small volume of free learning
  • Using JavaScript learning design patterns (2) | small volume of free learning
  • Using JavaScript learning design patterns (3) | small volume of free learning
  • Using JavaScript learning design patterns (4) | small volume of free learning

Behavior type

Iterator pattern

The iterator pattern provides a way to access the elements of an aggregate object sequentially without exposing the internal representation of the object.

The iterator pattern separates the process of iterating from the business logic. After using the iterator pattern, each element of the object can be accessed sequentially, even if the internal structure of the object is not concerned.

The simple class says its purpose is to iterate over an traversable object.

Methods such as forEach and map in JS are a kind of implementation of the iterator pattern. Generally speaking, we do not need to implement the iterator ourselves.

There is a kind of array in JS, they do not have iterative methods, for example, nodeList, arguments can not directly use iterative methods, you need to use jQuery each method or assemble the class number into a real array to iterate.

In the latest VERSION of ES6, for can be used for any data type that has an Iterator interface. of.. Iterating, and his bottom layer is the next method repeatedly called, specific reference nguyen Yifeng -Iterator and for… Of circulation.

example

We can implement an Iterator ourselves using the Iterator interface.

class Creater {
  constructor(list) {
    this.list = list;
  }
  // Create an iterator, also known as a traversator
  createIterator() {
    return new Iterator(this); }}class Iterator {
  constructor(creater) {
    this.list = creater.list;
    this.index = 0;
  }
  // Determine whether the data is traversed
  isDone() {
    if (this.index >= this.list.length) {
      return true;
    }
    return false;
  }
  next() {
    return this.list[this.index++]; }}var arr = [1.2.3.4];
var creater = new Creater(arr);
var iterator = creater.createIterator();
console.log(iterator.list); // [1, 2, 3, 4]
while(! iterator.isDone()) {console.log(iterator.next());
  / / 1
  / / 2
  / / 3
  / / 4
}
Copy the code

summary

  1. Ordered data sets in JavaScript include Array, Map, Set, String, typeArray, arguments, and NodeList, excluding Object
  2. Any data with the [symbol. iterator] interface deployed can be used for… The of loop traverses
  3. The iterator pattern separates the target object from the iterator object, conforming to the open closed principle

Subscribe/Publish model (Observer)

The publish/subscribe pattern, also known as the observer pattern, defines a one-to-many dependency between objects. When an object’s state changes, all dependent objects are notified. In JavaScrtipt, we generally use a time model to replace the traditional publish/subscribe model.

Examples include bidirectional binding and event mechanisms in Vue.

The difference between publish/subscribe and observer

  • Publishers can receive subscriptions directly, called observer mode

  • Publishers do not directly touch subscribers, but a unified third party does the communication, called publish/subscribe

example

You can implement your own event bus that emulates $emit and $ON

class EventBus {
  constructor() {
    this.callbacks = {};
  }
  $on(name, fn) {
    (this.callbacks[name] || (this.callbacks[name] = [])).push(fn);
  }
  $emit(name, args) {
    let cbs = this.callbacks[name];
    if (cbs) {
      cbs.forEach((c) = > {
        c.call(this, args);
      });
    }
  }
  $off(name) {
    this.callbacks[name] = null; }}let event = new EventBus();
event.$on("event1".(arg) = > {
  console.log("event1", arg);
});

event.$on("event2".(arg) = > {
  console.log("event2", arg);
});

event.$emit("event1".1); // event1 1
event.$emit("event2".2); // event2 2
Copy the code

The strategy pattern

Define a set of algorithms, encapsulate them one by one, and make them replaceable.

The purpose of the policy pattern is to separate the use of algorithms from the implementation of algorithms.

A policy pattern usually consists of two parts:

  • A set of variable policy classes that encapsulate specific algorithms and are responsible for specific computation
  • A set of immutable environment classes: once a request is received, it is subsequently delegated to a policy class

Indicates that the environment class maintains a reference to a policy object.

example

Using performance ratings to calculate bonuses, you could easily write the following code:

var calculateBonus = function(performanceLevel, salary) {
  if (performanceLevel === "S") {
    return salary * 4;
  }
  if (performanceLevel === "A") {
    return salary * 3;
  }
  if (performanceLevel === "B") {
    return salary * 2; }}; calculateBonus("B".20000); // Output: 40000
calculateBonus("S".6000); // Output: 24000
Copy the code

Modify code using the policy pattern:

var strategies = {
  S: (salary) = > {
    return salary * 4;
  },
  A: (salary) = > {
    return salary * 3;
  },
  B: (salary) = > {
    return salary * 2; }};var calculateBonus = function(level, salary) {
  return strategies[level](salary);
};
console.log(calculateBonus("S".200)); // Output: 800
console.log(calculateBonus("A".200)); // Output: 600
Copy the code

The state pattern

The state mode allows an object to change when its internal state changes

The state pattern mainly deals with situations where the conditional expressions governing the state of an object are too complex. Complex decision logic can be simplified by moving the decision logic of states into a series of classes that represent different states.

example

Implement a traffic light switch.

Click to view Demo: Traffic Lights – online example

If you are adding a blu-ray, you can simply add a blu-ray class and add the parssBtn method without changing the other states.

summary

  • By defining different state classes, the behavior of state can be changed according to the change of state. It is not necessary to write a lot of logic in the class of the object being operated, and it is easy to add new states.
  • In line with the principle of openness and closure

Interpreter mode

** Given a language, define a representation of its grammar and define an Interpreter that uses that representation to interpret sentences in the language.

Use less, you can refer to two articles to understand.

  • Design mode – Interpreter mode – JavaScript
  • A detailed explanation of the javascript design pattern’s interpreter pattern

summary

  • How is the description language syntax defined, interpreted, and compiled
  • For professional scenarios

The mediator pattern

Mediator Pattern is used to reduce the complexity of communication between multiple objects and classes.

This pattern provides a mediation class that typically handles communication between different classes and supports loose coupling, making code easy to maintain

Through a mediator object, all other related objects communicate rather than refer to each other, but when one of them changes, the mediator object is only notified.

The mediator pattern can be used to decouple objects from previous objects.

For example: Vuex

Reference link: JavaScript mediator pattern

summary

  • Isolate the associated objects through a mediator
  • In line with the principle of openness and closure
  • To reduce the coupling

Visitor pattern

In the Visitor Pattern, we use a Visitor class that changes the execution algorithm of the element class.

In this way, the element’s execution algorithm can change as visitors change.

example

Invoke the methods of the element class through the visitor.

/ / visitors
function Visitor() {
  this.visit = function(concreteElement) {
    concreteElement.doSomething(); // use doSomething() for whoever accesses it.
  };
}
/ / element class
function ConceteElement() {
  this.doSomething = function() {
    console.log("This is a concrete element.");
  };
  this.accept = function(visitor) {
    visitor.visit(this);
  };
}
// Client
var ele = new ConceteElement();
var v = new Visitor();
ele.accept(v); // This is a concrete element
Copy the code

summary

  • If there are operations on an object that are irrelevant (or weakly related) to the object, you can use the visitor pattern to encapsulate those operations in the visitor to prevent them from contaminating the object.
  • If similar operations exist in a group of objects, they can be encapsulated in visitors to avoid a lot of repetitive code.

Memo mode

The Memento Pattern stores a certain state of an object so that it can be restored at an appropriate time

example

Implement an “editor” with the function of saving records, including

  • Record changes in the state of an object over time
  • A previous state can be restored at any time (such as undo)
// Status memo
class Memento {
  constructor(content) {
    this.content = content;
  }
  getContent() {
    return this.content; }}// Cheat sheet
class CareTaker {
  constructor() {
    this.list = [];
  }
  add(memento) {
    this.list.push(memento);
  }
  get(index) {
    return this.list[index]; }}/ / editor
class Editor {
  constructor() {
    this.content = null;
  }
  setContent(content) {
    this.content = content;
  }
  getContent() {
    return this.content;
  }
  saveContentToMemento() {
    return new Memento(this.content);
  }
  getContentFromMemento(memento) {
    this.content = memento.getContent(); }}// Test the code
let editor = new Editor();
let careTaker = new CareTaker();

editor.setContent("111");
editor.setContent("222");
careTaker.add(editor.saveContentToMemento()); // Store memos
editor.setContent("333");
careTaker.add(editor.saveContentToMemento()); // Store memos
editor.setContent("444");

console.log(editor.getContent()); / / 444
editor.getContentFromMemento(careTaker.get(1)); / / cancel
console.log(editor.getContent()); / / 333
editor.getContentFromMemento(careTaker.get(0)); / / cancel
console.log(editor.getContent()); / / 222
Copy the code

summary

  • Separation of state objects from consumers (decoupling)
  • In line with the principle of openness and closure

Template method pattern

In Template Pattern, an abstract class exposes a method/Template that executes its methods.

Its subclasses can override method implementations as needed, but the calls will be made in the manner defined in the abstract class.

Feel used not a lot, want to know can click on the reference link below.

Reference: JavaScript design pattern template method pattern

Chain of Responsibility model

As the name suggests, the Chain of Responsibility Pattern creates a Chain of recipient objects for a request.

This pattern decouples the sender and receiver of the request by giving the type of request.

In this pattern, each receiver typically contains a reference to the other receiver.

If an object cannot handle the request, it passes the same request to the next recipient, and so on.

example

Reimbursement approval process of the company: Group leader = project manager = Financial Director

// Leave approval requires the approval of the team leader, the manager and finally the director
class Action {
  constructor(name) {
    this.name = name;
    this.nextAction = null;
  }
  setNextAction(action) {
    this.nextAction = action;
  }
  handle() {
    console.log(`The ${this.name}The examination and approval `);
    if (this.nextAction ! =null) {
      this.nextAction.handle(); }}}let a1 = new Action("Team leader");
let a2 = new Action("Project Manager");
let a3 = new Action("Finance director");
a1.setNextAction(a2);
a2.setNextAction(a3);
a1.handle();
// Group leader approval
// Project manager approval
// Finance director approval

// Divide an operation into multiple responsibilities, one after the other, and finally complete the operation.
Copy the code

summary

  • Think of chain operations like jQuery and Promise
  • The initiator is isolated from the handler
  • In line with the principle of closed development

Command mode

Command Pattern is a data-driven design Pattern, which belongs to behavior Pattern.

The request is wrapped in the object as a command and passed to the calling object.

The calling object looks for a suitable object that can handle the command and passes the command to the corresponding object, which executes the command.

example

Implement an editor with many commands, such as: write, read, and so on.

class Editor {
  constructor() {
    this.content = "";
    this.operator = [];
  }
  write(content) {
    this.content += content;
  }
  read() {
    console.log(this.content);
  }
  space() {
    this.content += "";
  }
  readOperator() {
    console.log(this.operator);
  }
  run(. args) {
    this.operator.push(args[0]);
    this[args[0]].apply(this, args.slice(1));
    return this; }}const editor = new Editor();

editor
  .run("write"."hello")
  .run("space")
  .run("write"."zkk!")
  .run("read"); // => 'hello zkk! '

// Outputs the operation queue
editor.readOperator(); // ["write", "space", "write", "read"]
Copy the code

summary

  • To reduce the coupling
  • New commands can be easily added to the system

Original from Ninety: links to original blog posts

This article is part of the “Gold Nuggets For Free!” Event, click to view details of the event