学习JavaScript设计模式(一)

来源:互联网 发布:公牛网络面板接线图 编辑:程序博客网 时间:2024/06/06 14:17

前言:

最近在读 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(); // 2basketModel.getTotalPrices(); // 128console.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(); // 2basketModel.getTotalPrices(); // 128console.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());   // truevar badSingletonA = badSingleton.getInstance();var badSingletonB = badSingleton.getInstance();console.log(badSingletonA.getPrivateRandomNumber() === badSingletonB.getPrivateRandomNumber());   // false

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

0 0
原创粉丝点击