めも帖

「めも帖」代わりにダラダラと書いていったり、めもしたりしているだけです。

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);
	}

}