Đây là điều giúp tôi hiểu được sự khác biệt, nhờ vào một bài đăng trên blog của Pascal Precht.
Dịch vụ là một phương thức trên một mô-đun có tên và chức năng xác định dịch vụ. Bạn có thể tiêm và sử dụng dịch vụ cụ thể đó trong các thành phần khác, như bộ điều khiển, chỉ thị và bộ lọc. Một nhà máy là một phương thức trên một mô-đun và nó cũng có một tên và một chức năng, xác định nhà máy. Chúng tôi cũng có thể tiêm và sử dụng nó giống như cách chúng tôi đã làm với dịch vụ.
Các đối tượng được tạo mới sử dụng giá trị của thuộc tính nguyên mẫu của hàm xây dựng của chúng làm nguyên mẫu, vì vậy tôi tìm thấy mã Angular gọi Object.create (), mà tôi tin là hàm xây dựng dịch vụ khi được khởi tạo. Tuy nhiên, một chức năng của nhà máy thực sự chỉ là một chức năng được gọi, đó là lý do tại sao chúng ta phải trả về một đối tượng theo nghĩa đen cho nhà máy.
Đây là mã 1,5 góc tôi tìm thấy cho nhà máy:
var needsRecurse = false;
var destination = copyType(source);
if (destination === undefined) {
destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
needsRecurse = true;
}
Đoạn mã nguồn góc cho hàm Factory ():
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
}
Nó lấy tên và hàm xuất xưởng được truyền và trả về một nhà cung cấp có cùng tên, có phương thức $ get là hàm xuất xưởng của chúng tôi. Bất cứ khi nào bạn yêu cầu người tiêm cho một phụ thuộc cụ thể, về cơ bản, nó sẽ hỏi nhà cung cấp tương ứng về một thể hiện của dịch vụ đó, bằng cách gọi phương thức $ get (). Đó là lý do tại sao $ get () là bắt buộc, khi tạo nhà cung cấp.
Đây là mã 1,5 góc cho dịch vụ.
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
Hóa ra khi chúng ta gọi dịch vụ (), nó thực sự gọi là nhà máy ()! Tuy nhiên, nó không chỉ chuyển chức năng xây dựng dịch vụ của chúng tôi cho nhà máy. Nó cũng truyền một hàm yêu cầu trình tạo khởi tạo một đối tượng bởi hàm tạo đã cho.
Nói cách khác, nếu chúng ta tiêm MyService ở đâu đó, điều xảy ra trong mã là:
MyServiceProvider.$get(); // return the instance of the service
Để phục hồi lại, một dịch vụ gọi một nhà máy, đó là phương thức $ get () trên nhà cung cấp tương ứng. Hơn nữa, $ kim phun.instantiate () là phương thức cuối cùng gọi Object.create () với hàm xây dựng. Đó là lý do tại sao chúng tôi sử dụng "cái này" trong các dịch vụ.
Đối với ES5, chúng tôi không sử dụng dịch vụ: dịch vụ () hoặc nhà máy (), đó luôn là một nhà máy được gọi là nhà cung cấp dịch vụ của chúng tôi.
Bạn cũng có thể làm điều tương tự với các dịch vụ. Dịch vụ là một hàm tạo, tuy nhiên, điều đó không ngăn chúng ta trả lại nghĩa đen của đối tượng. Vì vậy, chúng tôi có thể lấy mã dịch vụ của mình và viết nó theo cách mà về cơ bản nó thực hiện chính xác giống như nhà máy của chúng tôi hoặc nói cách khác, bạn có thể viết một dịch vụ như một nhà máy để trả về một đối tượng.
Tại sao hầu hết mọi người khuyên nên sử dụng các nhà máy hơn các dịch vụ? Đây là câu trả lời hay nhất mà tôi đã thấy xuất phát từ cuốn sách của Pawel Kozlowski: Làm chủ phát triển ứng dụng web với AngularJS.
Phương pháp nhà máy là cách phổ biến nhất để đưa các đối tượng vào hệ thống tiêm phụ thuộc AngularJS. Nó rất linh hoạt và có thể chứa logic sáng tạo tinh vi. Vì các nhà máy là các chức năng thông thường, chúng tôi cũng có thể tận dụng phạm vi từ vựng mới để mô phỏng các biến "riêng tư". Điều này rất hữu ích vì chúng tôi có thể ẩn chi tiết triển khai của một dịch vụ cụ thể. "