学习JavaScript设计模式(一)

前言:

最近在读 JavaScript 设计模式这本书。好记性不如烂笔头,在这里做个笔记加深自己的理解。
我们首先要了解一下几个概念:
模式:一种可复用的解决方案,可用于解决软件设计中所遇到的常见问题。
模式的优点:

  • 模式是已经验证的解决方案;
  • 模式很容易被服用;
  • 模式富有表达力;

模式的分类:

  • 创建型设计模式:构造器(Constructor)、工厂(Factory)、抽象(Abstract)、原型(Prototype)、单例(Singleton)、生成器(Builder)。
  • 结构型设计模式:装饰者(Decorator)、外观(Facade)、亨元(Flyweight)、适配器(Adapter)和代理(Proxy)。
  • 行为设计模式:迭代器(Iterator)、中介者(Mediator)、观察者(Observer)和访问者(Visitor)。

Model(模块)模式

模块是任何一个强大的应用程序框架必不可少的一部分。模块模式在某种程度上是基于对象字面量,通过闭包的方式封装私有状态和组织。
模块模式提供一种包装混合私有/公有方法和变量的方式,防止其泄露至全局作用域,并与别的开发人员接口冲突。

简单的模板实现:

/**
 * Created by Zang on 2017/3/12.
 * 通过 Model 模式模拟实现购物车
 */
var basketModel = (function () {
    // 私有
    var _items = [];
    return {
        // 公有
        addItem: function (item) {
            _items.push(item);
        },
        getItemCount: function () {
            console.log(_items.length);
        },
        getTotalPrices: function () {
            if (_items.length === 0) {
                console.log('购物车为空');
                return;
            }
            var totalPrices = 0.0;
            _items.forEach(function (item) {
                totalPrices += item.number * item.prices;
            });
            console.log(totalPrices);
        }
    };
})();

basketModel.addItem({
    name: 'JavaScript设计模式',
    number: 1,
    prices: 49.00
});
basketModel.addItem({
    name: '精通AngularJS',
    number: 1,
    prices: 79.00
});
basketModel.getItemCount(); // 2
basketModel.getTotalPrices(); // 128
console.log(basketModel._items); // undefined

优点:

  • 在 JavaScript立场,对于有面向对象背景的开发人员来说,相比真正的封装这样的代码更加简洁;
  • 支持私有数据;

缺点:

  • 无法为私有对象建立自动化单元测试;
  • BUG修正补丁时会增加额外的复杂性,我们必须覆盖所有与BUG的私有对象有交互的公有对象;
  • 开发人员无法轻易的扩展私有对象;

Revealing Model(揭示模块)模式

该模式是在模块模式的基础上进行改进。该模式在私有范围内简单定义所有的函数和变量,并返回一个匿名对象,它拥有指向私有函数的指针。

简单模板实现:(在Model示例基础上进行修改)

/**
 * Created by Zang on 2017/3/12.
 */
var basketModel = (function () {
    // 私有
    var _items = [];
    var _addItem = function (item) {
        _items.push(item);
    };
    var _getItemCount = function () {
        console.log(_items.length);
    };
    var _getTotalPrices = function () {
        if (_items.length === 0) {
            console.log('购物车为空');
            return;
        }
        var totalPrices = 0.0;
        _items.forEach(function (item) {
            totalPrices += item.number * item.prices;
        });
        console.log(totalPrices);
    };
    return {
        // 公有
        addItem: _addItem,
        getItemCount: _getItemCount,
        getTotalPrices: _getTotalPrices
    };
})();

basketModel.addItem({
    name: 'JavaScript设计模式',
    number: 1,
    prices: 49.00
});
basketModel.addItem({
    name: '精通AngularJS',
    number: 1,
    prices: 79.00
});
basketModel.getItemCount(); // 2
basketModel.getTotalPrices(); // 128
console.log(basketModel._items); // undefined

优点:除上述Model模式的优点外,其语法更加一致。很清晰的指出哪些是允许被公开访问的,可读性更高。
缺点:除上述Model模式的缺点外,其比Model模式更加脆弱。因为当一个私有对象指向公有函数,打补丁的时候不能将公有对象覆盖。

Singleton(单例)模式

单例模式限制了类的实例化次数只能是一次。当该实例不存在的时候,通过一个方法创建一个实例对象。如果存在则返回该对象的引用。
单例模式不同于我们使用的静态对象,我们可以推迟它的初始化。因为通常我们使用它时候需要一些信息,而这些信息在初始化阶段可能无法提供给我们。
在JavaScript中,单例充当的是共享资源命名空间,从全局命名空间中隔离出代码实现,从而为函数提供单一的访问接口。

简单模板实现:

/**
 * Created by Zang on 2017/3/12.
 */

var singleton = (function () {
    var instance = null;
    var init = function () {
        var _privateRandomNumber = Math.random();
        return {
            getPrivateRandomNumber: function () {
                return _privateRandomNumber;
            }
        };
    };
    return {
        getInstance: function () {
            if (!instance) {
                instance = init();
            }
            return instance;
        }
    };
})();

var badSingleton = (function () {
    var instance = null;
    var init = function () {
        var _privateRandomNumber = Math.random();
        return {
            getPrivateRandomNumber: function () {
                return _privateRandomNumber;
            }
        };
    };
    return {
        getInstance: function () {
            instance = init();
            return instance;
        }
    };
})();

var singletonA = singleton.getInstance();
var singletonB = singleton.getInstance();
console.log(singletonA.getPrivateRandomNumber() === singletonB.getPrivateRandomNumber());   // true

var badSingletonA = badSingleton.getInstance();
var badSingletonB = badSingleton.getInstance();
console.log(badSingletonA.getPrivateRandomNumber() === badSingletonB.getPrivateRandomNumber());   // false

单例很有使用价值,当我们需要使用它的时候,则表示我们需要重新评估我们的设计。
单例的存在往往表明系统模块要么是紧密耦合,要么是逻辑过于分散。单例通常是用来加强紧密耦合。

猜你喜欢

转载自blog.csdn.net/qq_20282263/article/details/61629347