问题描述:

This is a design pattern related question. I am not looking for an answer as to how to achieve the following, but rather the most widely accepted and way to achieve polymorphism in a service.

Suppose I had a service called getData. It needs to get some data, whether it be from a database, text file, or something hardcoded, and output it depending on what the settings are on the $scope in the controller. In this example below, suppose getData depends on the 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

}

}

}]);

Questions:

  1. How would you achieve this generally in Javascript? I am not sure about the best practices around achieving polymorphism in Javascript. I am used to using interfaces and dealing with the situation above by using dependency injection and passing in objects that adhere to the same interface, and call a common method, from the controller. Usually some other "class" would take care of selecting which object to instantiate and pass in, and therefore make the controller agnostic to concrete details as to "how it is done".

  2. How would one go about doing this in AngularJS?

    How would the pattern typically look? Can you give a "textbook" Angular way of achieving polymorphism?

网友答案:

I wanted to comment, but I realized it might be too long, so I'm going to post an answer.

If we are talking about ES5, polymorphism & inheritance can be achieved through prototyping.

For example:

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

In ES6 this can be done using class functions. You can read more about this, HERE ( it's gonna be very nice :D )

Below you'll find some code that might answer your question. Hope this is what you're looking for:

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;
    });
  }


});
相关阅读:
Top