AngularJS - 依存性注入:入門者のガイド

こんにちは、将来のプログラマーさんたち!今日は、AngularJSの世界とその最も強力な機能の1つである依存性注入(DI)に一緒に挑戦していきます。これらの用語が今は意味不明に聞こえるかもしれませんが、このチュートリアルの終わりまでには、プロのようにこれらを駆使できるようになるでしょう!

AngularJS - Dependency Injection

依存性注入とは?

本題に入る前に、まず依存性注入とは何かを理解しましょう。例えば、ケーキを作るとします。全ての材料を自分で集める代わりに、必要なものが必要なときに誰かが渡してくれる方が良いでしょう?これがプログラミングにおける依存性注入の基本的な考え方です。依存性注入は、あなたのコード(ケーキ)が正しく動作するために必要なコンポーネント(材料)を提供します。

では、AngularJSが依存性注入をどのように実装するかを探ってみましょう。

Value

Valueは依存性注入の最もシンプルな形式です。ケーキ作りの関数に単一の材料を渡すようなものです。

var app = angular.module('myApp', []);

app.value('playerName', 'LeBron James');

app.controller('PlayerCtrl', function($scope, playerName) {
$scope.name = playerName;
});

この例では、'playerName'というValueを作成し、コントローラーに注入しています。コントローラーはこのValueをローカル変数のように使用できます。

Factory

Factoryはケーキのミックスのように、オブジェクトを生成して返す関数です。Valueよりも複雑ですが、より多くの柔軟性があります。

app.factory('playerFactory', function() {
return {
name: 'Stephen Curry',
team: 'Golden State Warriors',
getInfo: function() {
return this.name + ' plays for ' + this.team;
}
};
});

app.controller('PlayerCtrl', function($scope, playerFactory) {
$scope.playerInfo = playerFactory.getInfo();
});

ここでは、プロパティとメソッドを持つオブジェクトを返すFactoryを作成しています。コントローラーはこのFactoryを使用して選手の情報にアクセスできます。

Service

ServiceはFactoryに似ていますが、オブジェクトを返す代わりに関数のインスタンスを返します。特定のケーキしか作らない専門のベーカリーのように考えられます。

app.service('PlayerService', function() {
this.name = 'Kevin Durant';
this.team = 'Phoenix Suns';
this.getInfo = function() {
return this.name + ' plays for ' + this.team;
};
});

app.controller('PlayerCtrl', function($scope, PlayerService) {
$scope.playerInfo = PlayerService.getInfo();
});

FactoryとServiceの主な違いは、どのようにインスタンス化されるかです。Serviceは常にシングルトンであり、アプリケーション全体にわたって1つのインスタンスしか存在しません。

Provider

ProviderはAngularJSにおける最も複雑な形の依存性注入です。完全に装備されたベーカリーのように、どんなケーキでもどんな材料でどんな方法ででも作れるものです。

app.provider('playerProvider', function() {
var defaultName = 'Giannis Antetokounmpo';

return {
setName: function(name) {
defaultName = name;
},
$get: function() {
return {
getName: function() {
return defaultName;
}
};
}
};
});

app.config(function(playerProviderProvider) {
playerProviderProvider.setName('Luka Doncic');
});

app.controller('PlayerCtrl', function($scope, playerProvider) {
$scope.playerName = playerProvider.getName();
});

Providerはサービスをアプリケーションが実行される前に設定することができます。この例では、設定フェーズで選手の名前を設定しています。

Constant

ConstantはValueに似ていますが、設定フェーズに注入できるため、アプリケーション全体で変更されない値に使用されます。ケーキのレシピを毎回正確に守るようなものです。

app.constant('GAME_DURATION', 48);

app.config(function(GAME_DURATION) {
console.log('A basketball game lasts ' + GAME_DURATION + ' minutes');
});

app.controller('GameCtrl', function($scope, GAME_DURATION) {
$scope.duration = GAME_DURATION;
});

Constantsはアプリケーション全体で変更されない値に非常に有用です。

例:バスケットボールチームマネージャの構築

これまでの全ての依存性注入の形式を合わせたより複雑な例を見てみましょう。

var app = angular.module('basketballApp', []);

// Constant
app.constant('MAX_PLAYERS', 15);

// Value
app.value('teamName', 'Angular All-Stars');

// Factory
app.factory('PlayerFactory', function() {
var players = [];
return {
addPlayer: function(name) {
players.push(name);
},
getPlayers: function() {
return players;
}
};
});

// Service
app.service('CoachService', function() {
this.name = 'Coach Angular';
this.motivate = function() {
return this.name + ' says: Let\'s win this game!';
};
});

// Provider
app.provider('gameProvider', function() {
var venue = 'Home Court';

return {
setVenue: function(v) {
venue = v;
},
$get: function() {
return {
getVenue: function() {
return venue;
}
};
}
};
});

app.config(function(gameProviderProvider) {
gameProviderProvider.setVenue('Angular Arena');
});

app.controller('TeamCtrl', function($scope, MAX_PLAYERS, teamName, PlayerFactory, CoachService, gameProvider) {
$scope.teamName = teamName;
$scope.maxPlayers = MAX_PLAYERS;
$scope.players = PlayerFactory.getPlayers();
$scope.coachMotivation = CoachService.motivate();
$scope.gameVenue = gameProvider.getVenue();

$scope.addPlayer = function(playerName) {
if ($scope.players.length < MAX_PLAYERS) {
PlayerFactory.addPlayer(playerName);
$scope.playerName = '';
} else {
alert('Team is full!');
}
};
});

出力

このアプリケーションを実行すると、完全に機能するバスケットボールチームマネージャができます。チームに選手を追加(最大許容数まで)し、コーチの激励を確認し、試合がどこで行われるかを知ることができます。

以下に、今回取り上げた依存性注入の形式をまとめた表を示します:

タイプ 説明 使用例
Value シンプルな値の注入 シンプルな値を注入するため
Factory オブジェクトを返す 複雑なロジックを持つサービスを作成するため
Service 関数のインスタンスを返す シングルトンのサービスを作成するため
Provider 設定可能なサービスファクトリー アプリケーションが実行される前に設定が必要なサービス
Constant 変更不可の値、設定フェーズで注入可能 アプリケーション全体で変更されない値

依存性注入をマスターする鍵は練習です。まずはシンプルな注入から始めて、徐々に複雑なシナリオに挑戦してみてください。それでは、将来的なAngularJSのマスターとして、编程を楽しんでください!

Credits: Image by storyset