JavaScriptは観察者モードを実現します.
5900 ワード
概念:
[wiki]観察者モードはソフトウェア設計モードの一種である.このようなモードでは、目標オブジェクトは、その観察者に依存するすべてのオブジェクトを管理し、その自身の状態が変化したときに、自動的に通知を発行する.これは、一般に、観察者によって提供される方法を呼び出して実現される.このようなモードは通常、リアルタイムイベント処理システムとして用いられる.
ES 5の実装
またES 5では主に
ES 6に追加されたProxyアプリは多くの用途があり、Reflect Appiと組み合わせて多くの強力な論理を簡単に実現できます.詳しくは「ECMAScript 6入門」、阮一峰の紹介を参照してください.実現コードは以下の通りです.
完全に実現する
[wiki]観察者モードはソフトウェア設計モードの一種である.このようなモードでは、目標オブジェクトは、その観察者に依存するすべてのオブジェクトを管理し、その自身の状態が変化したときに、自動的に通知を発行する.これは、一般に、観察者によって提供される方法を呼び出して実現される.このようなモードは通常、リアルタイムイベント処理システムとして用いられる.
ES 5の実装
またES 5では主に
Object.defineProperties
によりオブジェクト属性の設定(set)と取得(get)を定義し、設定を行う際に関連する処理関数を実行します.var targetObj={
age:1
}
function observer(oldval,newval){
console.log('name '+oldval+' '+newval);
}
Object.defineProperty(targetObj,'name',{
enumerable:true,
configurable:true,
get:function(){
return name;
},
set:function(val){
//
observer(name,val);
name=val;
}
});
targetObj.name="www";
targetObj.name="mmm";
console.info('targetObj:',targetObj);
結果:name www
name www mmm
targetObj:{age:1,name:"mmm"}
ES 6の実現(set方法で実現)class TargetObj{
constructor(age,name){
this.name=name;
this.age=age;
}
set name(val){
Observer(name,val);
name=val;
}
}
function Observer(oldval,newval){
console.info('name '+ oldval +' ' + newval);
}
let targetObj2 = new TargetObj(1,'www');
targetObj2.name="mmm";
console.info(targetObj2);
ReflectとProxyを使って実現ES 6に追加されたProxyアプリは多くの用途があり、Reflect Appiと組み合わせて多くの強力な論理を簡単に実現できます.詳しくは「ECMAScript 6入門」、阮一峰の紹介を参照してください.実現コードは以下の通りです.
class TargetObj {
constructor(age, name) {
this.name = name;
this.age = age;
}
}
let targetObj = new TargetObj(1, "www");
let observerProxy = new Proxy(targetObj, {
set(target, property, value, reciever) {
if (property === "name") {
observer(target[property], value);
}
Reflect.set(target, property, value, reciever);
}
});
function observer(oldval, newval) {
console.info(`name ${oldval} ${newval}`);
}
observerProxy.name="mmm";
console.info(targetObj);
結果:name www mmm
TargetObj {name: "mmm", age: 1}
共通観察者モード完全に実現する
let Observer = (function() {
// ,
var __messages = {};
return {
regist: function regist(type, fn) {
//
if (typeof __messages[type] === "undefined") {
//
__messages[type] = [fn];
} else {
//
__messages[type].push(fn);
}
return this;
},
fire: function fire(type, args) {
// ,
if (!__messages[type]) return;
//
var events = {
type: type,
args: args || {}
};
var i = 0;
var len = __messages[type].length;
//
for (; i < len; i++) {
//
__messages[type][i].call(this, events);
}
return this;
},
remove: function remove(type, fn) {
//
if (__messages[type] instanceof Array) {
//
var i = __messages[type].length - 1;
for (; i >= 0; i--) {
//
__messages[type][i] === fn && __messages[type].splice(i, 1);
}
}
}
};
})();
簡単に使うconst observerFns = {
test: "test",
addUser: "addUser"
};
Observer.regist(observerFns.test, e => {
console.log(e.type, e.args.msg);
})
.regist(observerFns.test, e => {
console.info(e.type, e.args.msg);
})
.regist(observerFns.addUser, e => {
var type = e.type;
var args = e.args;
console.log(args);
``;
});
Observer.fire(observerFns.test, { msg: " " });
Observer.fire(observerFns.addUser, { name: "wwm" });
結果test
test
Object {name: "wwm"}
クラス実現方法の自動呼び出しclass Student {
result: string;
constructor(result: string) {
this.result = result;
this.say = this.say.bind(this); // `class` `this`
}
say(e) {
console.log(this.result);
}
answer(question: string) {
//
Observer.regist(question, this.say);
}
sleep(question: string) {
console.log(this.result + " " + question + " ");
Observer.remove(question, this.say);
}
}
class Teacher {
ask(question) {
console.log(" : " + question);
Observer.fire(question, question);
}
}
var student1 = new Student(" 1 ");
var student2 = new Student(" 2 ");
var student3 = new Student(" 3 ");
var teacher = new Teacher();
student1.answer(" ");
student1.answer(" ");
student2.answer(" ");
student3.answer(" ");
student3.sleep(" ");
teacher.ask(" ");
teacher.ask(" ");
ES 5で使用するvar Student = function(result) {
var that = this;
that.result = result;
that.say = function() {
console.log(that.result);
};
};
Student.prototype.answer=function(question){
Observer.regist(question,this.say)
}
Student.prototype.sleep=function(question){
Observer.remove(question,this.say)
}
var Teacher=function(){};
Teacher.prototype.ask=function(question){
console.log(" : "+question);
Observer.fire(question,null)
}
var student1 = new Student(" 1 ");
var student2 = new Student(" 2 ");
var student3 = new Student(" 3 ");
var teacher = new Teacher();
student1.answer(" ");
student1.answer(" ");
student2.answer(" ");
student3.answer(" ");
student3.sleep(" ");
teacher.ask(" ");
teacher.ask(" ");
出力 3
:
1
2
:
1
3