A: What is the Observer model

An Observer is a design pattern in which a subject maintains a series of objects that depend on it, automatically notifying them of any changes in state. The observer pattern is a method by which an object, called a target, automatically notifies a set of observers it maintains of changes in its state.

Second, concrete implementation

We implement the Observer pattern using the following components:

  • Subject: Maintains a list of observers that can be added or removed easily.
  • Observer: Provides an update interface for objects that need to be notified when the target state changes.
  • ConcreteSubject: Notifies the Observer when a state changes, storing the ConcreteObserver state.
  • ConcreteObserver: Stores a reference to the ConcreteSubject that implements the Update interface of the Observer to align its state with the target state.

First, let’s simulate a series of dependency observers that a target might have:

Function ObserverList() {this.obServerList = []; } / / Add a observer ObserverList. The prototype. The Add = function (obj) {return this. ObserverList. Push (obj); }; / / to Empty all list ObserverList. Prototype. The Empty = function () {enclosing ObserverList = []; }; / / the number of view the current observer ObserverList prototype. Count = function () {return this. ObserverList. Length; }; / / Get the corresponding to the observer in the index ObserverList. Prototype. Get = function (index) {if (index > 1 && index < this. ObserverList. Length)  { return this.observerlist[index]; }}; / / to the head or the tail into a obj ObserverList. Prototype. An Inset = function (obj, index) {let pointer = 1; if (index === 0) { this.observerlist.unshift(obj); } else if (index === this.observerlist.length) { this.observerlist.push(obj); pointer = index; } return pointer; }; / / the incoming object to find the corresponding index ObserverList. Prototype. IndexOf = function (obj, startIndex) {let I = startIndex, pointer = 1; while (i < this.observerlist.length) { if (this.observerlist[i] === obj) { pointer = i; } i++; } return pointer; }; ObserverList.prototype.RemoveIndexAt = function (index) { if (index === 0) { this.observerlist.shift(); } else if (index === this.observerlist.length - 1) { this.observerlist.pop(); }}; Function extend(obj, extension) {for (let key in obj) {extension[key] = obj[key]; }}Copy the code

Next, let’s simulate the subject and the ability to add, remove, or notify observers to the list of observers

function Subject() { this.observers = new ObserverList(); } / / Add a observer Subject. Prototype. AddObserver = function (the observer) {this. Observers. The Add (observer); }; / / delete the Subject observer. Prototype. RemoveObserver = function (the observer) { this.observers.RemoveIndexAt(this.observers.IndexOf(observer, 0)); }; Noser. Notify = function (context) {let observerCount = this.observer.count (); for (let i = 0; i < observerCount; i++) { this.observers.Get(i).Update(context); }};Copy the code

Then define a framework to create a new Observer. Update can be customized based on service functions.

Function Observer () {this.update = function(context) {console.log(' I'm going to Update ', context); }}Copy the code

Now that a simple Observer pattern has been written, let’s use it for business purposes

We use the Observer pattern to implement a feature that controls all or unall selection of multiple checkboxes and notifies them accordingly.

A new Observer is added by clicking the button, and when the Subject is updated, we notify the appropriate Observer to make the update.

First, complete the establishment of DOM structure

<button id="addNewObserver">Add New Ovserver checkbox</button> <br> <div id="observersContasiner"></div>Copy the code

Then, the main logic will be written

Let controlCheckbox = document.getelementById ("mainCheckbox"); let addBtn = document.getElementById('addNewObserver'); let container = document.getElementById('observersContasiner'); // Extend controlCheckbox extend(new Subject(), controlCheckbox) with Subject; ControlCheckbox ["onclick"] =function () {controlcheckbox.notify (controlcheckbox.checked)}; AddBtn ["onclick"] = AddNewObserver; Concrete Observer function AddNewObserver () {// Create a new checkbox that needs to be added document.createElement("input"); check.type = 'checkbox'; // Extend checkbox extend(new Observer(), check); Check.Update = function(value){console.log(' all button updated ----'); check.checked = value; } / / give priority to the subject of observer controlCheckbox list to add a new observer. The AddObserver (check); // Attach the observer to the container. AppendChild (check); }Copy the code

At this point, we have completed the above functionality, attached below is the complete code

<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, Initial-scale =1.0" /> <title>Observer Observer mode </title> </head> <body> <button ID ="addNewObserver">Add New Ovserver <div id="observersContasiner"></div> <script> Function ObserverList() {this.obServerList = []; } / / Add a observer ObserverList. The prototype. The Add = function (obj) {return this. ObserverList. Push (obj); }; / / to Empty all list ObserverList. Prototype. The Empty = function () {enclosing ObserverList = []; }; / / the number of view the current observer ObserverList prototype. Count = function () {return this. ObserverList. Length; }; / / Get the corresponding to the observer in the index ObserverList. Prototype. Get = function (index) {if (index > 1 && index < this. ObserverList. Length)  { return this.observerlist[index]; }}; / / to the head or the tail into a obj ObserverList. Prototype. An Inset = function (obj, index) {let pointer = 1; if (index === 0) { this.observerlist.unshift(obj); } else if (index === this.observerlist.length) { this.observerlist.push(obj); pointer = index; } return pointer; }; / / the incoming object to find the corresponding index ObserverList. Prototype. IndexOf = function (obj, startIndex) {let I = startIndex, pointer = 1; while (i < this.observerlist.length) { if (this.observerlist[i] === obj) { pointer = i; } i++; } return pointer; }; ObserverList.prototype.RemoveIndexAt = function (index) { if (index === 0) { this.observerlist.shift(); } else if (index === this.observerlist.length - 1) { this.observerlist.pop(); }}; Function extend(obj, extension) {for (let key in obj) {extension[key] = obj[key]; } } /** * @description: * @param {*} * @return {*} */ function subject () {this.observers = new ObserverList(); } / / Add a observer Subject. Prototype. AddObserver = function (the observer) {this. Observers. The Add (observer); }; / / delete the Subject observer. Prototype. RemoveObserver = function (the observer) { this.observers.RemoveIndexAt(this.observers.IndexOf(observer, 0)); }; Noser. Notify = function (context) {let observerCount = this.observer.count (); for (let i = 0; i < observerCount; i++) { this.observers.Get(i).Update(context); }}; // The Observer function Observer () {this.update = function(context) {console.log(' I'm going to Update ', context); Let controlCheckbox = document.getelementById ("mainCheckbox"); let addBtn = document.getElementById('addNewObserver'); let container = document.getElementById('observersContasiner'); // Extend controlCheckbox extend(new Subject(), controlCheckbox) with Subject; ControlCheckbox ["onclick"] =function () {controlcheckbox.notify (controlcheckbox.checked)}; AddBtn ["onclick"] = AddNewObserver; Concrete Observer function AddNewObserver () {// Create a new checkbox that needs to be added document.createElement("input"); check.type = 'checkbox'; // Extend checkbox extend(new Observer(), check); Check.Update = function(value){console.log(' all button updated ----'); check.checked = value; } / / give priority to the subject of observer controlCheckbox list to add a new observer. The AddObserver (check); // Attach the observer to the container. AppendChild (check); } </script> </body> </html>Copy the code

Finally, if you find any problems, please correct them