JavaScript模式

单例模式

function Universe() {
    //缓存实例
    var instance;
    //重写构造函数
    Universe = function Universe() {
      return instance;
    };
    //保留原型属性
    Universe.prototype = this;
    //实例
    instance = new Universe();
    //重置构造函数指针
    instance.constructor = Universe;
    //所有功能
    instance. start_time =0;
    instance.bang = "Big";
    return instance;
}

另一种写法

var Universe;
(function() {
    var instance;
    Universe = function Universe() {
      if (instance) {
        return instance;
      }
      instance = this;
    
      this.start_time = 0;
      this.bang = "Big";
    }
}());

工厂模式

//父构造函数
function CarMaker() { }
// a method of the parent
CarMaker.prototype.drive = function () {
  return "Vroom, I have " + this.doors + " doors";
};
//静态工厂方法
CarMaker.factory = function (type) {
var constr = type,
  newcar;
//如果构造函数不存在,则发生错误
if (typeof CarMaker[constr] !== "function") {
  throw {
    name: "Error",
    message: constr + "doesn’t exist"
  };
}
if(typeof CarMaker[constr].prototype.drive !== "function") {
  CarMaker[constr].prototype = new CarMaker();
}
newcar = new CarMaker[constr]();
  return newcar;
};
CarMaker.Compact = function() {
  this.doors = 4;
}
CarMaker.Convertible = function() {
  this.doors = 2;
}
CarMaker.SUV = function() {
  this.doors = 24;
}

迭代模式

var agg = (function () {
    var index = 0,
      data = [1, 2, 3, 4, 5],
      length = data.length;
    return {
      next: function () {
        var element;
        if (!this.hasNext()) {
          return null;
        }
    
        element = data[index];
        index = index + 2;
        return element;
      },
      hasNext: function() {
        return index < length;
      },
      rewind: function() {
        index = 0;
      },
      current: function() {
        return data[index];
      }
    }
}());

装饰器模式

function Sale(price) {
    this.price = price || 100;
  }
  Sale.prototype.getPrice = function() {
    return this.price;
  }
  Sale.decorators = {};
  Sale.decorators.fedtax = {
    getPrice: function() {
      var price = this.uber.getPrice();
      price += price * 5 / 100;
      return price;
    }
  };
  Sale.decorators.quebec = {
    getPrice: function() {
      var price = this.uber.getPrice();
      price += price * 7.5 / 100;
      return price;
    }
  };
  Sale.decorators.money = {
    getPrice: function() {
      return "$" + this.uber.getPrice().toFixed(2);
    }
  };
  Sale.decorators.cdn = {
    getPrice: function() {
      return "CDN$ " + this.uber.getPrice().toFixed(2);
    }
  };
  Sale.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 validator = {
    types: {},
    messages: [],
    config: {},
    validate: function(data) {
      var i, msg, type, checker, result_ok;
      this.messages = [];
      for (i in data) {
        if (data.hasOwnProperty(i)) {
          type = this.config[i];
          checker = this.types[type];

          if(!type) {
            continue;
          }
          if (!checker) {
            throw {
              name: "ValidationError",
              messages: "No handler to validate type " + type
            };
          }
          result_ok = checker.validate(data[i]);
          if (!result_ok) {
            msg = "Invalid value for *" + i + "*, " + checker.instructions;
            this.messages.push(msg);
          }
        }
      }
      return this.hasErrors();
    },
    hasErrors() {
      return this.messages.length !== 0;
    }
  }
  validator.types.isNonEmpty = {
    validate: function(value) {
      return value !== "";
    },
    instructions: "the value cannot be empty"
  };
  validator.types.isNumber = {
    validate: function(value) {
      return !isNaN(value);
    },
    instructions: "the value can only be a valid number, e.g. 1, 3.14 or 2010"
  };
  validator.types.isAlphaNum = {
    validate: function(value) {
      return !/[^a-z0-9]/i.test(value);
    },
    instructions: "the value can only contain characters and numbers, no special symbols"
  };
  validator.config = {
    first_name: "isNonEmpty",
    age: "isNumber",
    username: "isAlphaNum",
  }
  var data = {
    first_name: "super",
    last_name: "Man",
    age: "unknown",
    username: "o_0"
  }
  validator.validate(data);
  if (validator.hasErrors()) {
    console.log(validator.messages.join("\n"));
  }

外观模式

var myevent = {
  stop: function(e) {
    if (typeof e.preventDefault === 'function') {
      e.preventDefault();
    }
    if (typeof e.stopPropagation === 'function') {
      e.stopPropagation();
    }
    if (typeof e.returnValue === 'boolean') {
      e.returnValue = false
    }
    if (typeof e.cancelBubble === 'boolean') {
      e.cancelBubble = true;
    }
  }
}

代理模式

作用:合并多个请求

var proxy = {
  ids: [],
  delay: 50,
  timeout: null,
  callback: null,
  context: null,
  makeRequest: function(id, callback, context) {
    this.ids.push(id);
    this.callback = callback;
    this.context = context;

    if(!this.timeout) {
      this.timeout = setTimeout(function() {
        proxy.flush();
      }, this.delay);
    }
  },
  flush: function() {
    http.makeRequest(this.ids, "proxy.handler");
    this.timeout = null;
    this.ids = [];
  },
  handler: function(data) {
    var i, max;
    if(parseInt(data.query.count, 10) === 1) {
      proxy.callback.call(proxy.context, data.query.results.Video);
      return;
    }
    for (i = 0, max = data.query.results.Video.length; i < max; i += 1) {
      proxy.callback.call(proxy.context, data.query.results.Video[i]);
    }
  }
};

中介者模式

// player constructor
function Player(name) {
    this.points = 0;
    this.name = name;
}
// play method
Player.prototype.play = function () {
    this.points += 1;
    mediator.played();
};

// the scoreboard object
var scoreboard = {
    
    // HTML element to be updated
    element: document.getElementById('results'),
    
    // update the score display
    update: function (score) {
        
        var i, msg = '';
        for (i in score) {
            if (score.hasOwnProperty(i)) {
                msg += '<p><strong>' + i + '<\/strong>: ';
                msg += score[i];
                msg += '<\/p>';
            }
        }
        this.element.innerHTML = msg;
    }
};


var mediator = {
    
    // all the players
    players: {},
    
    // 
    setup: function () {
        var players = this.players;
        players.home = new Player('Home');
        players.guest = new Player('Guest');
        
    },
    
    // someone plays, update the score
    played: function () {
        var players = this.players,
            score = {
                Home:  players.home.points,
                Guest: players.guest.points
            };
            
        scoreboard.update(score);
    },
    
    // handle user interactions
    keypress: function (e) {
        e = e || window.event; // IE
        if (e.which === 49) { // key "1"
            mediator.players.home.play();
            return;
        }
        if (e.which === 48) { // key "0"
            mediator.players.guest.play();
            return;
        }
    }
};


// go!
mediator.setup();
window.onkeypress = mediator.keypress;

// game over in 30 seconds
setTimeout(function () {
    window.onkeypress = null;
    alert('Game over!');
}, 30000);

观察者模式

var publisher = {
    subscribers: {
        any: [] // event type: subscribers
    },
    subscribe: function (fn, type) {
        type = type || 'any';
        if (typeof this.subscribers[type] === "undefined") {
            this.subscribers[type] = [];
        }
        this.subscribers[type].push(fn);
    },
    unsubscribe: function (fn, type) {
        this.visitSubscribers('unsubscribe', fn, type);
    },
    publish: function (publication, type) {
        this.visitSubscribers('publish', publication, type);
    },
    visitSubscribers: function (action, arg, type) {
        var pubtype = type || 'any',
            subscribers = this.subscribers[pubtype],
            i,
            max = subscribers.length;
            
        for (i = 0; i < max; i += 1) {
            if (action === 'publish') {
                subscribers[i](arg);
            } else {
                if (subscribers[i] === arg) {
                    subscribers.splice(i, 1);
                }
            }
        }
    }
};

/*
var s1 = {log: console.log},
    s2 = {err: console.error},
    s3 = {warn: console.warn};


publisher.subscribe(s1.log);
publisher.subscribe(s2.err);
publisher.subscribe(s3.warn);

publisher.publish({hello: "World"});

publisher.unsubscribe(s2.err);
publisher.publish("hello");


publisher.subscribe(s1.log, "log");
publisher.publish({obj: "log this object"}, "log");
*/

function makePublisher(o) {
    var i;
    for (i in publisher) {
        if (publisher.hasOwnProperty(i) && typeof publisher[i] === "function") {
            o[i] = publisher[i];
        }
    }
    o.subscribers = {any: []};
}

var paper = {
    daily: function () {
        this.publish("big news today");
    },
    monthly: function () {
        this.publish("interesting analysis", "monthly");
    }
};

makePublisher(paper);

var joe = {
    drinkCoffee: function (paper) {
        console.log('Just read ' + paper);
    },
    sundayPreNap: function (monthly) {
        console.log('About to fall asleep reading this ' + monthly);
    }
};

paper.subscribe(joe.drinkCoffee);
paper.subscribe(joe.sundayPreNap, 'monthly');

paper.daily();
paper.daily();
paper.daily();
paper.monthly();


makePublisher(joe);

joe.tweet = function (msg) {
    this.publish(msg);
};

paper.readTweets = function (tweet) {
    alert('Call big meeting! Someone ' + tweet);
};

joe.subscribe(paper.readTweets);

joe.tweet("hated the paper today");
var publisher = {
    subscribers: {
        any: []
    },
    on: function (type, fn, context) {
        type = type || 'any';
        fn = typeof fn === "function" ? fn : context[fn];
        
        if (typeof this.subscribers[type] === "undefined") {
            this.subscribers[type] = [];
        }
        this.subscribers[type].push({fn: fn, context: context || this});
    },
    remove: function (type, fn, context) {
        this.visitSubscribers('unsubscribe', type, fn, context);
    },
    fire: function (type, publication) {
        this.visitSubscribers('publish', type, publication);
    },
    visitSubscribers: function (action, type, arg, context) {
        var pubtype = type || 'any',
            subscribers = this.subscribers[pubtype],
            i,
            max = subscribers ? subscribers.length : 0;
            
        for (i = 0; i < max; i += 1) {
            if (action === 'publish') {
                subscribers[i].fn.call(subscribers[i].context, arg);
            } else {
                if (subscribers[i].fn === arg && subscribers[i].context === context) {
                    subscribers.splice(i, 1);
                }
            }
        }
    }
};


function makePublisher(o) {
    var i;
    for (i in publisher) {
        if (publisher.hasOwnProperty(i) && typeof publisher[i] === "function") {
            o[i] = publisher[i];
        }
    }
    o.subscribers = {any: []};
}

var game = {
    
    keys: {},

    addPlayer: function (player) {
        var key = player.key.toString().charCodeAt(0);
        this.keys[key] = player;
    },

    handleKeypress: function (e) {
        e = e || window.event; // IE
        if (game.keys[e.which]) {
            game.keys[e.which].play();
        }
    },
    
    handlePlay: function (player) {
        var i, 
            players = this.keys,
            score = {};
        
        for (i in players) {
            if (players.hasOwnProperty(i)) {
                score[players[i].name] = players[i].points;
            }
        }
        this.fire('scorechange', score);
    }
};

function Player(name, key) {
    this.points = 0;
    this.name = name;
    this.key  = key;
    this.fire('newplayer', this);
}

Player.prototype.play = function () {
    this.points += 1;
    this.fire('play', this);
};

var scoreboard = {
    
    element: document.getElementById('results'),
    
    update: function (score) {
        
        var i, msg = '';
        for (i in score) {
            if (score.hasOwnProperty(i)) {
                msg += '<p><strong>' + i + '<\/strong>: ';
                msg += score[i];
                msg += '<\/p>';
            }
        }
        this.element.innerHTML = msg;
    }
};


makePublisher(Player.prototype);
makePublisher(game);

Player.prototype.on("newplayer", "addPlayer", game);
Player.prototype.on("play",      "handlePlay", game);

game.on("scorechange", scoreboard.update, scoreboard);

window.onkeypress = game.handleKeypress;


var playername, key;
while (1) {
    playername = prompt("Add player (name)");
    if (!playername) {
        break;
    }
    while (1) {
        key = prompt("Key for " + playername + "?");
        if (key) {
            break;
        }
    }
    new Player(playername,  key);    
}
posted @ 2018-11-29 10:20  宇晴  阅读(261)  评论(0编辑  收藏  举报