JavaScriptのObserver
デザインパターンで「Observer」があるんですけれど...JavaScriptで実装するとどうなるのだろう、と思いまして書いてみました。
対象となるブラウザーは、
一応実装として
- monsterオブジェクトが、listenerオブジェクトを含むこと
- listenerオブジェクトにて実際に処理が書かれている
ということにて試してみました
listenerオブジェクトがinterfaceを継承すると、いいと思うんですけれど。JavaScriptだとどうしたらいいのかなあ...
HTML
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Observer</title> <script type="text/javascript" src="jquery.min.js"></script> <script type="text/javascript" src="listener.js"></script> <script type="text/javascript" src="viewListener.js"></script> <script type="text/javascript" src="monster.js"></script> <script> var slime = new monster('スライム'); slime.addListener(new listener('battle')); slime.addListener(new viewListener('view')); $(document).ready(function(){ $('#do_battle').click(function(){ slime.guard(1); }); }); </script> </head> <body> <div id="hp"></div> <span class="button" id="do_battle">戦う</span> </body> </html>
monster.js
/* Subjectクラス */ var monster = function(name){ this.intialize(name); } monster.prototype = { listener: {}, name: '', hp: 5, intialize: function(name) { this.name = name; }, voice: function(){ alert(this.name + 'だぞぉ'); }, guard: function(damage){ if(this.hp > 0){ this.hp = this.hp - damage; } // 通知 this.notify(); }, addListener: function(listener){ this.listener[listener.id] = listener; }, removeListener: function(listener){ delete this.listener[listener.id]; }, notify: function(){ for(var key in this.listener) { this.listener[key].update(this); } } }
listener.js
/* ConcreteObserverクラスに相当 */ var listener = function(id){ this.intialize(id); } listener.prototype = { id: '', monster: '', intialize: function(id){ this.id = id; }, update: function(monster){ this.monster = monster; if(this.monster.hp <= 0) { alert(monster.name + 'は、死んでいる'); }else if(this.monster.hp <= 2){ alert(monster.name + 'は、弱っている'); }else{ //alert(monster.name + 'のHPは、' + this.monster.hp); } } }
viewListener.js
/* ConcreteObserverクラスに相当 */ var viewListener = function(id){ this.intialize(id); } viewListener.prototype = { id: '', monster: '', intialize: function(id){ this.id = id; }, update: function(monster){ this.monster = monster; this.display(); }, display: function(){ $('#hp').html(this.monster.name + '/' + this.monster.hp); } }