デザインパターン

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());// ドラキーが現れた!

Proxy -プロキシ-

実態を利用者から隠す

Mediator -メディエータ-

仲介者を通して判断する

Observer -オブザーバ-

関係者全員に状態を通知する

Builder -ビルダー-

複雑な作り方を利用者から隠す