嗨,我已成功使用OOP和AngularJs已经有一段时间了(首先从angularjs with oop inheritance in action开始),提供的方法允许您将类定义为角度服务,稍后您可以扩展或继承这些类:
Application.factory('AbstractObject', [function () {
var AbstractObject = Class.extend({
virtualMethod: function() {
alert("Hello world");
},
abstractMethod: function() { // You may omit abstract definitions, but they make your interface more readable
throw new Error("Pure abstract call");
}
});
return AbstractObject; // You return class definition instead of it's instance
}]);
Application.factory('DerivedObject', ['AbstractObject', function (AbstractObject) {
var DerivedObject = AbstractObject.extend({
virtualMethod: function() { // Shows two alerts: `Hey!` and `Hello world`
alert("Hey!");
this._super();
},
abstractMethod: function() {
alert("Now I'm not abstract");
}
});
return DerivedObject;
}]);
Plunker:http://plnkr.co/edit/rAtVGAsNYggBhNADMeoT
使用所描述的方法,您可以定义精美集成到角度基础结构中的类。你可以从两个世界中获得各种漂亮的功能--OOP和AngularJs。依赖注入对于您的类是免费的,它使您的类变得简单,允许将大量样板控制器代码放入某个基类中,以后可以重用。
先前描述的AngularJs基础设施模块在所有100%上展开它的翅膀。当您尝试定义递归类定义(即递归聚合)时会出现问题,例如,您有两个类定义,如Blog
和Tag
Application.factory('Blog', ['Tag', function (Tag) {
var Blog = Class.extend({
tags: function() {
return this.tags;
}
});
return Blog;
}]);
Application.factory('Tag', ['Blog', function (Blog) {
var Tag = Class.extend({
Blogs: function() {
return this.blogs;
}
});
return Tag;
}]);
它不起作用,因为Blog
和Tag
都是自引用本身导致循环依赖。
最后一件事,我发现有点丑陋的解决方案在我的具体案例中解决了我的问题,但一般不起作用,正如我所说,它并不漂亮:
Application.factory('BlogNamespace', [function () {
var Blog = Class.extend({
tags: function() {
return this.tags;
}
});
var Tag = Class.extend({
Blogs: function() {
return this.blogs;
}
});
return {
Tag: Tag,
Blog: Blog
};
}]);
上述修复不起作用,因为名称空间也可能是循环依赖的主题。这意味着它不是所描述问题的解决方案,而是现在更深层次的问题。
关于如何解决一般情况下描述的问题的任何建议?
答案 0 :(得分:66)
循环依赖始终是混合关注的标志,这是一件非常糟糕的事情。 AngularJS的作者之一MiškoHevery解释了一个很好的解决方案on his awesome blog。简而言之,您可能在某处隐藏了第三个服务,这是您的代码中唯一真正需要的其他部分。
答案 1 :(得分:53)
我正在回答我自己的问题,因为我找到了解决我最初发布的问题的技术方法。但在此之前,我强烈建议您使用Blackhole的建议,因为它允许解决通常由不良架构引起的更广泛的问题。请首先使用他的方法,如果您知道自己在做什么,请返回当前的方法。
所以这里是:
您可以使用$injector
服务并在运行时注入所需的定义,从技术角度来看这是合法的,但再次根据this帖子(很难想象它是在2008年编写的) ),这就像一个黑魔法,这样做会让你反感:
Application.factory('Blog', ['$injector', function ($injector) {
var Tag = $injector.get('Tag'); // Here is your tag
...
}]);
Application.factory('Tag', ['Blog', function (Blog) {
...
}]);
事实证明,当前的方法是Service Locator模式的一个例子,它是IoC Antipattern。
答案 2 :(得分:1)
最后的度假村:没有鼓励
在我的情况下,以角度方式绕过这样的循环依赖问题的最佳方法是通过$rootScope
触发函数调用 - 广播。然后,另一个服务可以收听此广播并对所需的函数调用做出反应。它可能不是最优雅的解决方案,但在某些情况下,服务之间的交互主要是单向的,它可能是一个合理的替代方案。 (请注意,这也允许返回值仅通过回调传递回广播功能)
这样的一个伪示例是:
angular.module('myApp').factory('service1', ["$rootScope",
function($rootScope) {
function func1() {
// do something
}
$rootScope.$broadcast("callFunc2"); // calls func2 from service 1
return {
func1: func1
}
}
]);
angular.module('myApp').factory('service2', ["service1", "$rootScope",
function(service1, $rootScope) {
function func2() {
// do something
}
service1.func1(); // calls func1 from service 2
$rootScope.on("callFunc2", func2);
}
]);