在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'; } }); |
猫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!'; } }); |
根据达尔文的进化论,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!'; }; }); |
我们将豹和狼的动作特征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! }); |
这种方法一个明显的好处是,它使你的代码更好可测试,你可以创建一个物种,是一种混搭的各种性状triat,他们一定会如预期般运作的特点,只要有足够的单元测试。