javascript设计模式 – 依赖注入

定义

所有做过.net、java或者php开发的人都应该听过依赖注入dependency injection(DI)或者inverse of control(IOC)控制反转,依赖注入是一种软件设计模式,它让人移除硬生生的写死的依赖关系,让人可以修改它们。依赖可以通过构造函数、定义方法或者设置属性来注入对象。

依赖注入好处

减小对象与依赖之间的藕合关系。
不需要对原代码进行修改,直接可以应用到当前代码。
有助于把客户与设计隔离开,减小设计改变带来的影响。
让系统不用修改当前代码就可以重新配置。
可以进行并行或者独立开发。
让代码更好维护和测试,因为用其他依赖包或者模版代替的话依赖的影响可以被消除。

依赖注入缺点

当要实例化一种类型,你必须要知道要用什么依赖。
隐藏了类型的实例化和依赖关系解释逻辑后,如果发生错误比较难查找问题。
要求你要写更多的代码。
可能会运行得更慢,因为要以新的关键字来实例化一种类型,把必须要用的相关的关键字对应解释实例化。

简单的依赖注入实现代码

以简单的买卖为例:
一单买卖,必须有买方和卖方参与

    function Injector() {
        this.dependencies = {};
    }
    Injector.prototype.register = function (key, value) { // 注册依赖
        this.dependencies[key] = value;
    }
    Injector.prototype.resolve = function (deps, func, scope) { // 创建并解释注入依赖后的函数
        var args = [];
        scope = scope || {};
        for (var i = 0; i < deps.length, d = deps[i]; i++) {
            if (this.dependencies[d]) {
                scope[d] = this.dependencies[d];
            } else {
                throw new Error('Can\'t resolve ' + d);
            }
        }
        return function () {
            func.apply(scope || {}, Array.prototype.slice.call(arguments, 0));
        }
    }
    // 另一种写法,类require.js
    Injector.prototype.define = function (deps, callback) { // 创建并解释注入依赖
        var args = [];
        for (var i = 0; i < deps.length, d = deps[i]; i++) {
            if (this.dependencies[d]) {
                args.push(this.dependencies[d]);
            } else {
                throw new Error('Can\'t resolve ' + d);
            }
        }
        if (typeof (callback)==='function')
            callback.apply(this, args);
    }

    var myInjector = new Injector();

    var buy = function () { // 一个buy模块
      this.name="Nelson";
      this.start = function(){
	    document.writeln(this.name + ' bought some thing' + '<br>');
      }
    }
    var sell = function () { // 一个sell模块
      this.name='Jim';
      this.start = function () {
            document.writeln(this.name + ' sold some thing' + '<br>');
      }					
    }

    myInjector.register('buy', new buy()); // 注册依赖模块
    myInjector.register('sell', new sell()); // 注册依赖模块

    var deal = myInjector.resolve(['buy', 'sell'], function (deal) { // 创建并解释注入依赖buy和sell后的函数
        document.writeln(this.buy.name + '<br>');
        this.buy.start();
        document.writeln(this.sell.name + '<br>');
        this.sell.start();
        document.writeln(deal + ' relies on both ' + this.buy.name + ' and ' + this.sell.name + '<br><br>');
        this.buy.name = 'Han Meimei';
        this.sell.name = 'Li Lei';					
    });

    deal("Deal");
    console.log(myInjector);
    // 另一种写法
    myInjector.define(['buy', 'sell'], function (b, s) { // 注入依赖buy和sell
        document.writeln('New Name: ' + b.name + '<br>');
        b.start();				
        document.writeln('New Name: ' + s.name + '<br>');
        s.start();
        document.writeln('A deal relies on both ' + b.name + ' and ' + s.name + '<br>');
    });

作者: 博主

Talk is cheap, show me the code!

发表评论

电子邮件地址不会被公开。

Captcha Code