JavaScript设计模式

1.Constructor(构造器)模式

声明一个首字母大写的function,通过在构造器前面加new关键字,实例化一个对象。

可以使用原型来定义函数,原型定义的函数,不同的对象可以共用。

当function为方法,return起作用并且this为windows即全局;当function为对象,始终为return this,this表示这个对象。

 

// Constructor pattern
function Car(modal, year, miles) {
    this.modal = modal;
    this.year = year;
    this.miles = miles;

    // 这个方法会覆盖prototype中的toString方法
    this.toString = function() {
        return this.modal + " in object toString function";
    }
}

Car.prototype.toString = function() {
    return this.modal + " in prototype toString function";
};

var a = new Car("a", 2009, 20000);
var b = new Car("b", 2011, 1000);

console.log(a.toString());
console.log(b.toString());

 

2.Module(模块)模式

可以直接声明一个module对象。也可以执行一个函数,返回一个module对象,执行函数时可以引入一些变量(如JQuery、Underscore)。

对拥有面向对象背景的开发人员来说更整洁,而且它支持私有数据。

// 引入了jQuery和Underscore
var myModule = (function($) {
    // 私有变量
    var privateVar = "private";
    // 私有函数
    function privateMethod() {
        $("body").html("test");
    };

    return {
        // 公有变量
        publicVar: "public",
        // 公有函数
        publicMethod: function() {
            privateVar += "Var";
            privateMethod();
            console.log(privateVar);
        }
    };
})(jQuery);
// 调用公有函数
myModule.publicMethod()

 

3.观察者(Observer)模式

 观察者模式定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己。

// Observer pattern
function Observer() {
    this.stack = [];
}
Observer.prototype = {
    subscribe: function(fn) {
        this.stack.push(fn);
    },
    unsubscribe: function(fn) {
        this.stack = this.stack.filter(
            function(el) {
                if (el !== fn) {
                    return el;
                }
            }
        );
    },
    update: function(o, thisObj) {
        var scope = thisObj || window;
        this.stack.forEach(
            function(el) {
                el.call(scope, o);
            }
        );
    }
};

//测试
var o = new Observer;
var f1 = function(data) {
    console.log('Robbin: ' + data + ', 赶紧干活了!');
};
var f2 = function(data) {
    console.log('Randall: ' + data + ', 找他加点工资去!');
};

o.subscribe(f1);
o.subscribe(f2);

o.update("Tom回来了!")

//退订f1
o.unsubscribe(f1);
//再来验证
o.update("Tom回来了!");

 

观察者的使用场合就是:当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。

总的来说,观察者模式所做的工作就是在解耦,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化。

 

4.Prototype(原型)模式

Prototype模式为一种基于现有对象模板,通过克隆方式创建对象的模式。

可以通过Object.create创建一个拥有指定原型和对象的属性,也可以通过函数模仿构造函数创建。

// 使用Object.create方法
var vehicle = {
    getModel: function () {
        console.log('车辆的模具是:' + this.model);
    }
};
// 可以在Object.create的第二个参数里使用对象字面量传入要初始化的额外属性.
var car = Object.create(vehicle, {
    'id': {
        value: MY_GLOBAL.nextId(),
        enumerable: true // 默认writable:false, configurable:false
 },
    'model': {
        value: '福特',
        enumerable: true
    }
});

 

5.Command(命令)模式

用于将一个请求封装成一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及执行可撤销的操作。也就是说改模式旨在将函数的调用、请求和操作封装成一个单一的对象,然后对这个对象进行一系列的处理。此外,可以通过调用实现具体函数的对象来解耦命令对象与接收对象。

var CarManager = {
    // 请求信息
    requestInfo: function(model, id) {
        return 'The information for ' + model + ' with ID ' + id + ' is foobar';
    },
    // 购买汽车
    buyVehicle: function(model, id) {
        return 'You have successfully purchased Item ' + id + ', a ' + model;
    }
};
// 添加执行的函数
CarManager.execute = function(name) {
    return CarManager[name] && CarManager[name].apply(CarManager,[].slice.call(arguments, 1))
}

// 执行
CarManager.execute("arrangeViewing", "Harry Potter", "10000");

 

命令模式为我们提供了一种分离职责的手段,这些职责包括从执行命令的任意地方发布命令以及将该职责转而委托给不同对象。

实施明智的、简单的命令对象把action动作和调用该动作的对象绑定在一起。它们始终包括一个执行操作(如 run()或 execute())。所有具有相同接口的Command对象可以根据需要轻松交换,这被认为是该模式的一个更大的好处。

 

6.Factory(工厂)模式

Factory模式通过提供一个通用接口来创建对象。如果对象创建过程相对比较复杂,这种方法特别有用,例如,如果它强烈依赖于动态因素或应用程序配置的话。

var AbstractVehicleFactory = (function(){
    // 存储车辆类型
    var types = [];
    return {
        getVehicle: function( type, customizations ) {
            var Vehicle = types[type];
            return (Vehicle) ? new Vehicle(customizations) : null;
        },
        registerVehicle: function( type, Vehicle ) {
            var proto = Vehicle.prototype;
            // 可以加条件判断注册满足何种条件的车辆
            types[type] = Vehicle;
            return AbstractVehicleFactory;
        }
    }
})();

// 定义Car的构造函数
function Car(options) {
    // 默认值
    this.doors = options.doors || 4;
    this.state = options.state || "brand new";
    this.color = options.color || "sliver";
}

// 用法
AbstractVehicleFactory.registerVehicle("car", Car);

// 基于抽象车辆类型实例化一个新的car对象
var car = AbstractVehicleFactory.getVehicle("car", {
    color: "lime green",
    state: "like new"
});

适用场景

  • 当对象或组件设置涉及高复杂性时
  • 当需要根据所在的不同环境轻松生成对象的不同实例时
  • 当处理很多共享相同属性的小型对象或组件时
  • 在编写只需要满足一个API契约(亦称鸭子类型)的其他对象的实例对象时。对于解耦是很有用的

 

网址链接:http://cnsks.free3v.net/ .

匡时在辽宁鞍山祝家人朋友同学,新春快乐,万事如意!

posted @ 2014-01-29 21:23  匡时@下一站.info  阅读(307)  评论(0编辑  收藏  举报