JavaScript设计模式整理

栏目: 后端 · 发布时间: 5年前

内容简介:设计模式是程序员通识知识,熟练掌握并使用各种设计模式,可以体现一个程序员的工程开发水平。我花了几天时间,重温并整理了30多种设计模式,以JavaScript为示例语言。下面我会列出一些常用的设计模式说明及示例,更全面的内容见:一个模式就是一个可重用的方案,可应用于在软件设计中的常见问题。另一种解释就是一个我们如何解决问题的模板 - 那些可以在许多不同的情况里使用的模板。创建型设计模式:

写在前面

设计模式是 程序员 通识知识,熟练掌握并使用各种设计模式,可以体现一个程序员的工程开发水平。我花了几天时间,重温并整理了30多种设计模式,以JavaScript为示例语言。下面我会列出一些常用的 设计模式 说明及示例,更全面的内容见: https://github.com/yzsunlei/javascript-design-mode

什么是设计模式?

一个模式就是一个可重用的方案,可应用于在软件设计中的常见问题。另一种解释就是一个我们如何解决问题的模板 - 那些可以在许多不同的情况里使用的模板。

设计模式的分类:

创建型设计模式:

1、简单工厂模式

2、工厂方法模式

3、抽象工厂模式

4、建造者模式

5、原型模式

6、单例模式

结构型设计模式:

7、外观模式

8、适配器模式

9、代理模式

10、装饰者模式

11、桥接模式

12、组合模式

13、享元模式

行为型设计模式:

14、模板方法模式

15、观察者模式

16、状态模式

17、策略模式

18、职责链模式

19、命令模式

20、访问者模式

21、中介者模式

22、备忘录模式

23、迭代器模式

24、解释器模式

技巧型设计模式:

25、链模式

26、委托模式

27、数据访问对象模式

28、节流模式

29、简单模板模式

30、惰性模式

31、参与者模式

32、等待者模式

架构型设计模式:

33、同步模块模式

34、异步模块模式

35、Widget模式

36、MVC模式

37、MVP模式

38、MVVM模式

  • 备注:该分类借鉴于《JavaScript设计模式-张容铭》

工厂方法模式:

通过对产品类的抽象使其创建业务主要负责用于创建多类产品的实例。

// 安全模式创建的工厂类
var Factory = function(type, content) {
    if (this instanceof Factory) {
        // 保证是通过new进行创建的
        var s = new this[type](content);
        return s;
    } else {
        return new Factory(type, content);
    }
};

// 工厂原型中设置创建所有类型数据对象的基类
Factory.prototype = {
    Java: function(content) {

    },
    Php: function(content) {

    },
    JavaScript: function(content) {

    }
};

原型模式:

用原型实例指向创建对象的类,使用于创建新的对象的类共享原型对象的属性以及方法。

// 图片轮播类
var LoopImages = function(imgArr, container) {
    this.imagesArray = imgArr;
    this.container = container;
};

LoopImages.prototype = {
    // 创建轮播图片
    createImage: function() {
        console.log("LoopImages createImage function");
    },
    // 切换下一张图片
    changeImage: function() {
        console.log("LoopImages changeImage function");
    }
};

// 上下滑动切换类
var SliderLoopImg = function(imgArr, container) {
    // 构造函数继承图片轮播类
    LoopImages.call(this, imgArr, container);
};
SliderLoopImg.prototype = new LoopImages();
// 重写继承的“切换下一张图片”方法
SliderLoopImg.prototype.changeImage = function() {
    console.log("SliderLoopImg changeImage function");
};

单例模式:

又称单体模式,是只允许实例化一次的对象类。

// 惰性
var LarySingle = (function() {
    // 单例实例引用
    var _instance = null;
    // 单例
    function Single() {
        // 这里定义私有属性和方法
        return {
            publicMethod: function() {},
            publicProperty: "1.0"
        };
    }
    // 获取单例对象接口
    return function() {
        // 如果未创建单例将创建单例
        if(!_instance){
            _instance = Single();
        }
        // 返回单例
        return _instance;
    };
})();

外观模式:

为一组复杂的子系统接口提供一个更高级的统一接口,通过这个接口使得对子系统接口的访问更容易。

function addEvent(dom, type, fn) {
    // 对于支持DOM2级事件处理程序addEventListener方法的浏览器
    if (dom.addEventListener) {
        dom.addEventListener(type, fn, false);
    } else if (dom.attachEvent) {
        // 对于不支持addEventListener方法但支持attchEvent方法的浏览器
        dom.attachEvent("on" + type, fn);
    } else {
        // 对于不支持addEventListener方法,也不支持attchEvent方法,但支持“on”+事件名的浏览器
        dom["on" + type] = fn;
    }
}

装饰者模式:

在不改变原对象的基础上,通过对其进行包装拓展(添加属性或方法)使原对象可以满足用户更复杂需求。

var decorator = function (input, fn) {
    // 获取事件源
    var input = document.getElementById(input);
    // 若事件源已经绑定事件
    if (typeof input.click === 'function') {
        // 缓存事件源原有回调函数
        var oldClickFn = input.click;
        // 为事件源定义新的事件
        input.click = function () {
            // 事件源原有回调函数
            oldClickFn();
            // 执行事件源新增回调函数
            fn();
        }
    } else {
        // 事件源未绑定事件,直接为事件源添加新增回调函数
        input.onclick = fn;
    }
}

观察者模式:

又称发布-订阅者模式或消息机制,定义一种依赖关系,解决了主体对象与观察者之间功能的耦合。

var Observer = (function () {
    var __messages = {};
    return {
        // 注册消息
        register: function (type, fn) {
            if (typeof __messages[type] === 'undefined') {
                __messages[type] = [fn];
            } else {
                __messages[type].push(fn);
            }
        },
        // 发布消息
        fire: function (type, args) {
            if (!__messages[type])
                return;
            var events = {
                type: type,
                args: args || {}
            };
            var i = 0;
            var len = __messages[type].length;
            for (; i < len; i++) {
                __messages[type][i].call(this, events);
            }
        },
        // 移除消息
        remove: function (type, fn) {
            if (__messages[type] instanceof Array) {
                var i = __messages[type].length - 1;
                for (; i >= 0; i--) {
                    __messages[type][i] == fn && __messages[type].splice(i, 1);
                }
            }
        }
    }
})();

状态模式:

当一个对象的内部状态发生改变时,会导致其行为的改变,这看起来像是改变了对象。

// 状态对象
var ResultState = function () {
    var States = {
        state0: function () {
            console.log("第一种情况");
        },
        state1: function () {
            console.log("第二种情况");
        },
        state2: function () {
            console.log("第三种情况");
        },
        state3: function () {
            console.log("第四种情况");
        }
    };

    function show(result) {
        States['state' + result] && States['state' + result]();
    }

    return {
        show: show
    }
}();

命令模式:

将请求与实现解耦并封装成独立对象,从而使不同的请求对客户端的实现参数化。

// 绘图命令
var CanvasCommand = (function () {
   var canvas = document.getElementById('canvas');
   var ctx = canvas.getContext('2d');
   var Action = {
       fillStyle: function (c) {
           ctx.fillStyle = c;
       },
       fillRect: function (x, y, w, h) {
           ctx.fillRect(x, y, w, h);
       },
       strokeStyle: function (c) {
           ctx.strokeStyle = c;
       },
       strokeRect: function (x, y, w, h) {
           ctx.strokeRect(x, y, w, h);
       },
       fillText: function (text, x, y) {
           ctx.fillText(text, x, y);
       },
       beginPath: function () {
           ctx.beginPath();
       },
       moveTo: function (x, y) {
           ctx.moveTo(x, y);
       },
       lineTo: function (x, y) {
           ctx.lineTo(x, y);
       },
       arc: function (x, y, r, begin, end, dir) {
           ctx.arc(x, y ,r, begin, end, dir);
       },
       fill: function () {
           ctx.fill();
       },
       stroke: function () {
           ctx.stroke();
       }
   };
   return {
       excute: function (msg) {
           if (!msg)
               return;
           if (msg.length) {
               for (var i = 0, len = msg.length; i < len; i++) {
                   arguments.callee(msg[i]);
               }
           } else {
               msg.param = Object.prototype.toString.call(msg.param) === "[object Array]" ? msg.param : [msg.param];
               Action[msg.command].apply(Action, msg.param);
           }
       }
   }
})();

迭代器模式:

在不暴露对象内部结构的同时,可以顺序的访问聚合对象内部的元素。

// 迭代器
var Iterator = function (items, container) {
    var container = container && document.getElementById(container) || document;
    var items = container.getElementsByTagName(items);
    var len = items.length;
    var idx = 0;
    var splice = [].splice();

    return {
        first: function () {},
        second: function () {},
        pre: function () {},
        next: function () {},
        get: function () {},
        dealEach: function () {},
        dealItem: function () {},
        exclusive: function () {}
    }
};

链模式:

通过在对象方法中将当前对象返回,实现对同一个对象多个方法的链式调用。

var A = function (selector) {
    return new A.fn.init(selector);
};
A.fn = A.prototype = {
    constructor: A,
    init: function (selector) {
        console.log(this.constructor);
    }
};
A.fn.init.prototype = A.fn;

节流模式:

对重复的业务逻辑进行节流控制,执行最后一次操作并取消其他操作,以提高性能。

var throttle = function () {
    var isClear = arguments[0];
    var fn;
    if (typeof isClear === 'boolean') {
        fn = arguments[1];
        fn.__throttleID && clearTimeout(fn.__throttleID);
    } else {
        fn = isClear;
        param = arguments[1];
        var p = extend({
            context: null,
            args: [],
            time: 30
        }, param);
        arguments.callee(true, fn);
        fn.__throttleID = setTimeout(function () {
            fn.apply(p.context, p.args);
        }, p.time);
    }
}

参与者模式:

在特定的作用域中执行给定的函数,并将参数原封不动的传递。

// 函数绑定
function bind(fn, context) {
    return function () {
        return fn.apply(context, arguments);
    }
}

// 函数柯里化
function curry(fn) {
    var Slice = [].slice;
    var args = Slice.call(arguments, l);
    return function () {
        var addArgs = Slice.call(arguments);
        var allArgs = args.concat(addArgs);
        return fn.apply(null, allArgs);
    }
}

参考资料


以上所述就是小编给大家介绍的《JavaScript设计模式整理》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

腾讯方法

腾讯方法

潘东燕、王晓明 / 机械工业出版社 / 2014-12-11 / 39.00

这是国内第一本深度讲述腾讯产品研发与团队转型的书。本书介绍了腾讯三个不同生命周期的产品的开发过程,包括如何踏足新领域开发新产品;如何救活一个即将半路夭折的产品;如何让一个老产品持续盈利。本书呈现了互联网产品开发时会遇到普遍问题和解决方法,涉及大企业如何内部创业,并迅速组建新的项目团队;如何实现跨部门的合作;在面临新团队和紧急开发任务时如何提高团队沟通效率;在产品研发方面,如何定位产品、如何敏捷开发......一起来看看 《腾讯方法》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具