【问题标题】:AngularJS How To Achieve Polymorphism / Dependency Injection (Best Practices)AngularJS如何实现多态/依赖注入(最佳实践)
【发布时间】:2016-04-04 04:35:45
【问题描述】:

这是一个与设计模式相关的问题。我不是在寻找如何实现以下目标的答案,而是寻找最广泛接受的在服务中实现多态性的方法。

假设我有一个名为 getData 的服务。它需要获取一些数据,无论是来自数据库、文本文件还是硬编码的东西,并根据控制器中 $scope 上的设置进行输出。在下面的示例中,假设 getData 依赖于 dataSource。

angular.module('testApp').controller('testController'), [$scope, myAwesomeService, function ($scope, myAwesomeService){
    $scope.dataSource = 'database'; //defines the source of the data

    $scope.getData = function() {
        //use myAwesomeService, get the data and output

        if($scope.dataSource ==='database') {
             return //do it the first way
        }            

        else if($scope.dataSource ==='text') {
             return //do it the second way
        } 

        else if($scope.dataSource ==='csvfile') {
             return //do it the third way
        } 
        else if($scope.dataSource ==='form') {
             return //do it the fourth way
        } 

    }

}]);

问题:

  1. 您通常如何在 Javascript 中实现这一点?我不确定在 Javascript 中实现多态性的最佳实践。我习惯于使用接口并通过使用依赖注入并传入遵循相同接口的对象并从控制器调用通用方法来处理上述情况。通常,其他一些“类”会负责选择要实例化和传入的对象,因此控制器对“如何完成”的具体细节是不可知的。

  2. 如何在 AngularJS 中做到这一点? 该模式通常看起来如何?你能给出一个实现多态的“教科书”Angular 方法吗?

【问题讨论】:

    标签: javascript angularjs oop polymorphism


    【解决方案1】:

    我想发表评论,但我意识到它可能太长了,所以我将发布一个答案。

    如果我们谈论ES5,多态性和继承可以通过原型设计来实现。

    例如:

    function Auto(name,year){
       this.year=year;
       this.name=name;
    }
    Auto.prototype.showYear = function(){
       console.log(this.year);
    }
    
    function Car(name,year, model){
       Auto.call(this,name,year);
       this.model=model;
    }
    Car.prototype = Object.create(Auto.prototype);
    
    //usage
    var car = new Car('BMW',2015,'320d');
    car.showYear(); // will output 2015
    

    ES6 中,这可以使用class 函数来完成。您可以阅读更多关于此的信息,HERE(这会非常好:D)

    您会在下面找到一些可以回答您的问题的代码。希望这是您正在寻找的:

    function BaseService(){
        this.dataSource='database';
    }
    BaseService.prototype.getData = function(){
        console.log('base: get data');
    }
    
    
    function TextService(){
        this.dataSource='text';
    }
    TextService.prototype  = new BaseService();
    TextService.prototype.getData = function(){
        console.log('child text: get data');
    }
    
    
    
    function CsvService(){
        this.dataSource='csv';
    }
    CsvService.prototype  = new BaseService();
    CsvService.prototype.getData = function(){
        console.log('child csv: get data');
    }
    
    
    function FormService(){
        this.dataSource='form';
    }
    FormService.prototype  = new BaseService();
    FormService.prototype.getData = function(){
        console.log('child form: get data');
    }
    
    
    
    angular.module('myApp').factory('awesomeService', function(){
    
        var service={};
    
        service.getData = function(dataSource){
    
            var sourceService;
    
            if(dataSource='database'){
                 sourceService= new BaseService();
            }
    
            if(dataSource=='text'){
                sourceService=new TextService();
            }
    
            if(dataSource=='csv'){
               sourceService = new CsvService();
            }
    
            if(dataSource=='form'){
              sourceService= new FormService();
            }
    
            return sourceService.getData(); // i'm going to assume getData returns a promise
       }
    
       return service;
    
    });
    
    angular.module('myApp').controller('myController', function($scope,awesomeService){
      var myDataSource='database';
    
      $scope.getData = function(){
        awesomeService.getData(myDataSource).then(function(data){
             $scope.result=data;
        });
      }
    
    
    });
    

    【讨论】:

    • 感谢您的快速回复。在 Angular 上下文中,您会将 BaseService()、TextSerivce() 等放在哪里?几乎没有实现细节,它已经很长而且很难导航。将这些服务放入自己的angular服务中,将BaseService、TextService等一一注入到“awesomeService”中,是否普遍做法?
    • 这不是书面规定。这取决于您如何构建应用程序的样板。例如,我会将它们放在一个“dataService”中,我们将把它注入到其他服务中; angular.factory('dataService',function(){ var service={}; service.BaseService= function BaseService(){}; service.BaseService.prototype.getData= function(){}; service.TextService = function TextService( ){} service.TextService.prototype = new service.BaseService(); return service; });
    • 如果有可能在 awesomeService 之外需要它们(并且它们可能至少用于测试),请将它们设为服务。由于它们是在 awesomeService 中实例化的,它们应该是 factory 服务,而不是 service
    • 您能否详细说明工厂服务与角度服务?您是指角度上下文中的工厂与服务,还是您指的是其他东西?即你的意思是工厂:angular.module('myApp').factory('myFactory', function(){});
    • 在服务函数中将作为构造函数调用,而在工厂中,主函数将作为函数调用。 (服务返回主函数;工厂返回主函数的返回对象)我所有的例子都是用 .factory 编写的。
    猜你喜欢
    • 2010-12-11
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 2011-12-30
    • 2010-12-13
    • 1970-01-01
    • 2014-02-20
    相关资源
    最近更新 更多