Preface:
Recently, I browsed an article on the Internet about an overview of software design patterns, which is relatively clear and understandable.
http://c.biancheng.net/view/1317.html
1. Introduction of observer mode
In the real world, many objects do not exist independently, and a change in the behavior of one or more objects may lead to a change in the behavior of one or more other objects, such as: a red light stops; a bell rings at the end of a class and all students leave the classroom to move freely, and so on.
The same is true in the software world, for example, the relationship between data in Excel and polyline, pie and column charts; the relationship between models and views in MVC mode; the event source and event handler in event model. All of these are very convenient to implement in observer mode.
Definition and characteristics of patterns
Definition of Observer mode: A one-to-many dependency among multiple objects in which all dependent objects are notified and automatically updated when the state of an object changes. This mode is sometimes referred to as Publish-Subscribe mode, Model-View mode, and it is an object behavior mode.
The observer mode is an object behavior mode with the following main advantages.
Decreases the coupling between the target and the observer, which is abstract. Compliant with the principle of inversion of dependency.
A trigger mechanism is established between the target and the observer.
Its main drawbacks are as follows.
The dependency between the target and the observer is not completely broken, and circular references may occur.
When there are many observer objects, the publication of notifications takes a lot of time, which affects the efficiency of the program.
2. Observer Simple Code
We use code abstraction to understand the observer's principles and the shortcomings described above:
abstract class Subject { protected observers: Observer[] = []; //Increase Observer Method public add(observer: Observer): void{ this.observers.push(observer); } //Delete Observer Method public remove(observer: Observer): void { this.observers.pop()// Simple use of pseudocode for deletion } public abstract notifyObserver(): any; //Notify Observer Method } //Specific objectives class ConcreteSubject extends Subject { public notifyObserver(): void{ this.observers.forEach((obs) => { obs.response(); }); } } //Abstract observer interface Observer { response(): any; //reaction } //Specific Observer 1 class ConcreteObserver1 implements Observer { public response(): void{ cc.log("Specific observer 1 responds!"); } } //Specific Observer 1 class ConcreteObserver2 implements Observer { public response(): void{ cc.log("Specific observer 2 responds!"); } } //When used let subject: Subject = new ConcreteSubject(); let obs1: Observer = new ConcreteObserver1(); let obs2: Observer = new ConcreteObserver2(); subject.add(obs1); subject.add(obs2); subject.notifyObserver();
3. Use of observers in cocosCreator
We use observers for decoupling purposes, such as cc.game provided in the engine:
1. Define events anywhere: cc.game.on;
2. Distribute events anywhere: cc.game.dispatchEvent;
It's quite convenient to use, but remember to delete since you've registered to listen for events; sometimes I like to implement one myself, or sometimes I need to write a similar observer myself.
Not rigorous but to show the observer's internal logic:
export default class EventCenter { private static eventMap: Map<string, EventHandler[]> = new Map<string, EventHandler[]>(); //Event Registration static registEvent(eventName: string, callBack: Function, target: Object): void { if (eventName == undefined || callBack == undefined || target == undefined) { return; } if (this.eventMap.get(eventName) == undefined) { this.eventMap[eventName] = new Array<EventHandler>(); } let handler: EventHandler = new EventHandler(target, callBack); EventCenter.eventMap[eventName].push(handler); } //Event Distribution static postEvent(eventName: string, param?: any): void { //Distribution can pass parameters let handlers = EventCenter.eventMap[eventName]; if (handlers == undefined) { return; } for (let i = 0; i < handlers.length; i++) { let handler = handlers[i] try { handlers.callBack.call(handler.target, param); } catch (errer) { cc.log(errer.message); cc.log(errer.stack.toString()); } } } //Delete Events static removeEvent(eventName: string, callBack: Function, target: Object): void { let handlers = EventCenter.eventMap[eventName]; if (handlers == undefined) { return; } for (let i = 0; i < handlers.length; i++) { let handler = handlers[i] if (handler != undefined && handler.target == target && handler.callBack == callBack) { handler[i] = undefined; break; } } } } //Structure of events class EventHandler { target: object; callBack: Function; constructor(target: object, callBack: Function) { this.target = target; this.callBack = callBack; } }