在Angular.js使用组合+依赖注入而不是继承

13-11-22 banq
I ♥ Angular.js - Write Better, Flexible Code By Us

在Angular.js,您创建的每个对象(控制器,服务或工厂)是一个纯老javascript的对象(POJO)。POJO是小功能是独立的不继承任何其他对象 ,可轻松地测试和可扩展性。听起来可能不是很多,但是在大规模应用程序中实现去耦逻辑,这是非常重要的。

不要使用继承,继承导致代码耦合。

比如下面代码:

var Mammal = Backbone.Model.extend({
    isAlive: true,
    
    init: function () {
        console.log('An animal is born');
    },
    
    eat: function (food) {
        return 'omnomnom, I\'m eating: ' + food;
    },
    
    sleep: function () {
        return 'zzzzz' ;
    },
    
    die: function () {
        this.isAlive = false;
        return 'I\'m dead!';
    }
});
 
var Cat = Mammal.extend({
    meow: function () {
        return 'meow meow';
    }
});
 
var Dog = Mammal.extend({
    bark: function () {
        return 'woof woof';
    }
});
<p>

猫cat和狗dog继承Mammal,接下来如果需要扩展,比如猫狗是不能用来打猎吃的,如果我们需要豹panther和狼wolf,以及猎人杀死它们,可以看出,豹和狼虽然都是食肉特征,但是它属于不同的分类,添加这些食肉特征会导致重复代码,都有hunt和kill方法:

var Panther = Cat.extend({
    hunt: function () {
        return 'imma go search for food!';
    },
    
    kill: function (animal) {
        animal.die();
        return animal + ' is dead!';
    }
});
 
var Wolf = Dog.extend({
    hunt: function () {
        return 'imma go search for food!';
    },
    
    kill: function (animal) {
        animal.die();
        return animal + ' is dead!';
    }
});
<p>

根据达尔文的进化论,the traits that adapt to the environment the most make the organisms survive the best. 最适应环境的特征(trait)能让生物生存的最好。

许多生物体的特点可以是相似的,即使它们不属于相同的属或科。

使用组合方式实现如下:

var animals = angular.module('animals', []);
 
animals.factory('Mammal', function Mammal () {
    this.init();
    
    this.init = function () {
        this.isAlive = true;
        console.log('An animal is born');
    };
    
    this.eat = function (food) {
        return 'omnomnom, I\'m eating: ' + food;
    };
    
    this.sleep = function () {
        return 'zzzzz' ;
    };
    
    this.die = function () {
        this.isAlive = false;
        return 'I\'m dead!';
    };
});
 
animals.service('meowingTrait', function () {
    this.meow = function () {
        return 'meow meow';
    }
});
 
animals.service('barkingTrait', function () {
    this.bark = function () {
        return 'woof woof';
    };
});
 
animals.service('huntingTrait', function () {
    this.hunt = function () {
        return 'imma go search for food!';
    };
    
    this.kill = function (animal) {
        animal.die();
        return animal + ' is dead!';
    };
});
<p>

我们将豹和狼的动作特征trait以animals.service('huntingTrait',.)方式实现,这个特征trait独立成一个类,然后通过依赖注入将这个特征注入到具体实例中。如:

// Angular.js uses dependency injection to inject the traits you
// need for your animal.
animals.factory('Cat', function (meowingTrait) {
    // use the meowing trait here.
});
 
animals.factory('Dog', function (barkingTrait) {
    // use the barking trait here.
});
 
animals.factory('Panther', function (meowingTrait, huntingTrait) {
    // meow or hunt, pick what you please!
});
 
animals.factory('Wolf', function (barkingTrait, huntingTrait) {
    // bark or hunt, or do both!
});
<p>

这种方法一个明显的好处是,它使你的代码更好可测试,你可以创建一个物种,是一种混搭的各种性状triat,他们一定会如预期般运作的特点,只要有足够的单元测试。

1
猜你喜欢