1. Module(模块)模式

var testModule = (function(){
  var counter = 0;
  return {
    incrementCounter: function() {
      return ++counter;
    },
    resetCounter: function() {
      conter = 0;
    }
  };
})();

// 增加计数器
testModule.incrementCounter();

2. Revealing Module(揭示模块)模式

var myRevealingModule = (function (){
  var privateCounter = 0;
  function privateFunction () {
    privateCounter++;
  }

  function publicIncrement () {
    privateFunction();
  }

  function publicFunction () {
    publicIncrement();
  }

  function publicGetCount () {
    return privateCounter;
  }

  myRevealingModule.start();

  // 将暴露的共有指针指向到私有函数和属性上
  return {
    start: publicFunction,
    increment: publicIncrement,
    count: publicGetCount
  }
})();

3. Singleton(单例)模式

var mySingleton = (function () {
  // 实例保持了 Singleton 的一个引用
  var instance;
  function init() {
    // Singleton 私有方法和变量
    function privateMethod () {
      console.log('i am private');
    }
    var privateRandomNumber = Math.random();
    return {
      // 公有方法和变量
      publicMethod: function () {
        console.log('The public can see me!');
      },
      getRandomNumber: function () {
        return privateRandomNumber;
      }
    };
  }

  return {
    // 获取 Singleton 的实例,如果存在就返回,不存在就创建新实例
    getInstance: function () {
      if (!instance) {
        instance = init();
      } else {
        return instance;
      }
    }
  };
})();

4. Observer(观察者)模式

// 一个目标可能拥有的一系列 Observer
function ObserverList () {
  this.observerList = [];
}

ObserverList.prototype.Add = function(obj) {
  return this.observerList.push(obj);
}
ObserverList.prototype.Empty = function() {
  this.observerList = [];
}
ObserverList.prototype.Count = function() {
  return this.observerList.length;
}
ObserverList.prototype.Get = function(index) {
  if (index > -1 && index < this.observerList.length) {
    return this.observerList[index];    
  }
}
ObserverList.prototype.Insert = function (obj, index) {
  // ...
}
ObserverList.prototype.IndexOf = function (obj, startIndex) {
  // ...
}
ObserverList.prototype.RemoveIndexAt = function (index) {
  // ...
}

// 模拟目标,以及在其上添加、删除或通知观察者
function Subject () {
  this.observers = new ObserverList();
}

Subject.prototype.AddObserver = function (observer) {
  this.observers.Add(observer);
}

Subject.prototype.RemoveObserver = function (observer) {
  this.observers.RemoveIndexAt(this.observers.IndexOf(observer));
}

Subject.prototype.Notify = function (context) {
  var observerCount = this.observers.Count();
  for (var i = 0; i < observerCount; i++) {
    // 观察者模式的最核心之处
    // 要求每个观察者必须要有固定的函数用来接收更新,这里就是 Update 函数
    this.observers.Get(i).Update(context);
  }
}

function Observer () {
  this.Update = function () {
    // ...
  }
}

4.1 Publish/Subscribe(发布/订阅)模式

// 相比观察者模式,发布/订阅模式使用了一个 Event Channel,用于解耦观察者与目标

var pubsub = {};
(function(q){
  var topics = {},
      subUid = -1;
  
  // 发布或广播事件,包含特定的 topic 名称和参数(比如传递的数据)
  q.publish = function (topic, args) {
    if (!topics[topic]) {
      return false;
    }

    var subscribers = topics[topic],
        len = subscribers ? subscribers.length : 0;
    while (len--) {
      subscribers[len].func(topic, args);
    }
    return this;
  };

  // 通过特定的名称和回调函数订阅事件,topic/event 触发时执行事件
  q.subscribe = function (topic, func) {
    if (!topics[topic]) {
      topics[topic] = [];
    }
    var token = (++subUid).toString();
    topics[topic].push({
      token: token,
      func: func
    });
    return token;
  };

  // 基于订阅上的标记引用,通过特定 topic 取消订阅
  q.unsubscribe = function (token) {
    for (var m in topics) {
      if (topics[m]) {
        for (var i = 0, j = topics[m].length; i < j; i++) {
          if (topics[m][i].token === token) {
            topics[m].splice(i, 1);
            return token;
          }
        }
      }
    }
    return this;
  };
})(pubsub);

5. Mediator(中介者)模式

var mediator = (function(){
  // 存储可被广播或监听的 event
  var events = {};

  // 订阅一个 event,提供一个回调函数,一旦 event 被广播就执行该回调
  var subscribe = function (event, fn) {
    if (!events[event]) {
      events[event] = [];
    }
    events[event].push({
      context: this,
      callback: fn
    });
    return this;
  }

  var publish = function (event) {
    var args;
    if (!events[event]) {
      return false;
    }
    args = Array.prototype.slice.call(arguments, 1);
    for (var i = 0, l = events[event].length; i < l; i++) {
      var subscription = events[event][i];
      subscription.callback.apply(subscription.context, args);
    }
    return this;
  };

  return {
    Publish: publish,
    Subscribe: subscribe,
    installTo: function (obj) {
      obj.subscribe = subscribe
      obj.publish = publish;
    }
  }
})();

6. Prototype(原型)模式

var vehiclePrototype = {
  init: function (carModel) {
    this.model = carModel;
  },
  getModel: function () {
    console.log('The model of this vehicle is..' + this.model);
  }
};

function vehicle (model) {
  function F () {}
  F.prototype = vehiclePrototype;

  var f = new F();
  f.init(model);
  return f;
}

var car = vehicle('Ford Escort');
car.getModel();

7. Command(命令)模式

// old
var CarManager = {
  requestInfo: function () {},
  buyVehicle: function () {},
  arrangeViewing: function () {}
}
// new 
CarManager.execute = function (name) {
  return CarManager[name] && CarManager[name].apply(CarManager, [].slice.call(arguments, 1));
}
// use
CarManager.execute('buyVehicle', 'Ford Escort', '454545');

8. Facade(外观)模式

// 提供高层次的接口,抹平和隐藏底层的复杂性
var addMyEvent = function(el, ev, fn) {
    if (el.addEventListener) {
        el.addEventListener(ev, fn, false);
    } else if (el.attachEvent) {
        el.attachEvent('on' + ev, fn, false);
    } else {
        el['on' + ev] = fn;
    }
}

9. Factory(工厂)模式

// 定义 Car 构造函数
function Car(options) {
    this.doors = options.doors || 4;
    this.state = options.state || 'brand new';
    this.color = options.color || 'silver';
}

// 定义 Truck 构造函数
function Truck(options) {
    this.state = options.state || 'used';
    this.wheelSize = options.wheelSize || 'large';
    this.color = options.color || 'blue';
}

// vehicle 工厂函数
function VehicleFactory() {}
VehicleFactory.prototype.vehicleClass = Car;
// 创建新 vehicle 实例的工厂方法
VehicleFactory.prototype.createVehicle = function(options) {
    if (options.vehicleType === 'car') {
        this.vehicleClass = Car;
    } else {
        this.vehicleClass = Truck;
    }
    return new this.vehicleClass(options);
}

9.1 Abstract Factory(抽象工厂)模式

支付宝扫码打赏 微信打赏

坚持原创技术分享,您的支持将鼓励我继续创作!

扫描二维码,分享此文章

逆葵's Picture
逆葵

网名逆葵。北邮土著,CS 硕士在读。《Vue.js 权威指南》作者之一。学习、思考、沉淀中, 向成为顶级 JavaScript 技术栈开发者努力。