デザインパターン
design pattern
JavaScriptのコードを例にして各デザイナパターンを示す
Singleton -シングルトン-
実物はひとつだけ生成
// 通常のオブジェクト
var obj1 = function(){
myid : 1
};
var obj2 = function(){
myid : 1
};
obj1 === obj2; //false
obj1 == obj2; //false
Iterator -イテレータ-
集約されたデータに順にアクセスする
var iterator = (function (){
var i = 0;
var data = [1, 2, 3, 4, 5];
var length = data.length;
return {
next : function (){
var element;
if(!this.hasNext()){
return null;
}
element = data[i];
i = i + 2;
return element;
},
hasNext : function (){
return i < length;
}
};
}());
while(iterator.hasNext()){
console.log(iterator.next());
}
Decorator デコレタ--
機能を加えていく
function Calc (num){
this.num = num || 3;
}
Calc.prototype.getNum = function (){
return this.num;
}
Calc.decorators = {};
Calc.decorators.add = {
getNum : function (){
var num = this.uber.getNum();
num = num + 5;
return num;
}
};
Calc.decorators.del = {
getNum : function (){
var num = this.uber.getNum();
num = num - 1;
return num;
}
};
Calc.prototype.decorate = function(decorator){
var F = function (){},
overrides = this.constructor.decorators[decorator],
i, newobj;
F.prototype = this;
newobj = new F();
newobj.uber = F.prototype;
for(i in overrides){
if(overrides.hasOwnProperty(i)){
newobj[i] = overrides[i];
}
}
return newobj;
};
var calc = new Calc(3);
console.log(calc.getNum()); // 3
console.log(calc = calc.decorate('add'));
console.log(calc.getNum()); // 8
console.log(calc = calc.decorate('del'));
console.log(calc.getNum()); // 7
Strategy -ストラテジー-
対象に応じて処理を変更する
var validator = function(){
types: {},
messages : {},
config : [],
validate :function(data){
var i, msg, type, checker, result_ok;
this.message = [];
for(i in data){
if(data.hasOwnProperty(i)){
type = this.config[i];
checker = this.types[type];
if(!type){
continue;
}
//検証処理
if(!checker){
throw{
name : "ValidationError",
message : "Error" + type,
};
}
result_ok = checker.validate(data[i]);
if(!result_ok){
msg = "Invalid value" + i + checker.instructions;
this.messages.push(msg);
}
}
}
return this.messages.length !== 0;
},
hasErrors : function(){
return this.message.length !==0;
}
};
validator.types.isNonEmpty = {
validate : function(value){
return value !== "";
},
instrucions : "値を入力してください"
};
validator.types.isNumber = {
validate : function(value){
return !isNaN(value);
},
instrucions : "数値のみを入力してください"
};
validator.types.isMAlphaNum = {
validate : function(value){
return !/[^a-zA-Z0-9]/i.test(value);
},
instrucions : "半角英数字のみを入力してください"
};
var data = {
name : 'Yukari',
age : '17',
account : 'yukarin800',
};
validator.config = {
name : 'isMonEmpty',
age : 'isNumber',
account : 'isMAlphaNum',
};
validator.validate(data);
if(validator.hasErrors()){
console.log(validator.messages.join("\n"););
}
Facade -ファサード-
代替のインターフェイスを用意する
Factory -ファクトリー-
同じ種類の物を同工程でつくれるようにする
function MonsterMaker(){}
MonsterMaker.prototype.drive = function (){
return this.name + "が現れた!";
};
MonsterMaker.factory = function(type){
var constr = type,
new_monster;
if(typeof MonsterMaker[constr] !== "function"){
throw {
name : "Error",
message : constr + " コンストラクタがありません"
};
}
if(typeof MonsterMaker[constr].prototype.drive !== "function"){
MonsterMaker[constr].prototype = new MonsterMaker();
}
new_monster = new MonsterMaker[constr]();
return new_monster
}
MonsterMaker.Slime = function (){
this.name = "スライム";
};
MonsterMaker.Doraki = function (){
this.name = "ドラキー";
};
var slime = MonsterMaker.factory('Slime');
var doraki = MonsterMaker.factory('Doraki');
console.log(slime.drive()); // スライムが現れた!
console.log(doraki.drive());// ドラキーが現れた!