นี่คือสิ่งที่ช่วยให้ฉันเข้าใจความแตกต่างขอบคุณโพสต์บล็อกโดย Pascal Precht
บริการเป็นวิธีการในโมดูลที่ใช้ชื่อและฟังก์ชั่นที่กำหนดบริการ คุณสามารถฉีดและใช้บริการนั้นในส่วนประกอบอื่น ๆ เช่นตัวควบคุมคำสั่งและตัวกรอง โรงงานเป็นวิธีการในโมดูลและยังใช้ชื่อและฟังก์ชั่นที่กำหนดโรงงาน นอกจากนี้เรายังสามารถฉีดและใช้วิธีเดียวกับที่เราทำกับบริการ
วัตถุที่สร้างด้วยการใช้ใหม่จะใช้ค่าของคุณสมบัติต้นแบบของฟังก์ชันคอนสตรัคเตอร์ของพวกเขาเป็นต้นแบบดังนั้นฉันจึงพบรหัส Angular ที่เรียกว่า Object.create () ซึ่งฉันเชื่อว่าเป็นฟังก์ชันตัวสร้างบริการเมื่อได้รับอินสแตนซ์ อย่างไรก็ตามฟังก์ชั่นจากโรงงานเป็นเพียงฟังก์ชั่นที่ได้รับการเรียกซึ่งเป็นสาเหตุที่เราต้องส่งคืนตัวอักษรวัตถุสำหรับโรงงาน
นี่คือรหัส 1.5 เชิงมุมที่ฉันพบสำหรับโรงงาน:
var needsRecurse = false;
var destination = copyType(source);
if (destination === undefined) {
destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
needsRecurse = true;
}
ข้อมูลโค้ดเชิงมุมสำหรับฟังก์ชั่น factory ():
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
}
มันใช้ชื่อและฟังก์ชั่นโรงงานที่ถูกส่งผ่านและส่งคืนผู้ให้บริการด้วยชื่อเดียวกันที่มีวิธีการ $ รับซึ่งเป็นฟังก์ชั่นโรงงานของเรา เมื่อใดก็ตามที่คุณถามหัวฉีดสำหรับการพึ่งพาที่เฉพาะเจาะจงนั้นโดยทั่วไปจะถามผู้ให้บริการที่เกี่ยวข้องสำหรับตัวอย่างของการบริการนั้นโดยเรียกวิธีการ $ get () นั่นเป็นเหตุผลว่าทำไมต้องใช้ $ get () เมื่อสร้างผู้ให้บริการ
นี่คือรหัส 1.5 เชิงมุมสำหรับการให้บริการ
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
ปรากฎว่าเมื่อเราเรียกบริการ () มันจะเรียกโรงงาน () จริง ๆ ! อย่างไรก็ตามมันไม่เพียงส่งผ่านฟังก์ชั่นตัวสร้างบริการของเราไปยังโรงงานตามที่เป็นอยู่ นอกจากนี้ยังผ่านฟังก์ชั่นที่ถามหัวฉีดเพื่อสร้างอินสแตนซ์วัตถุโดยตัวสร้างที่กำหนด
กล่าวอีกนัยหนึ่งถ้าเราฉีด MyService ที่ไหนสักแห่งสิ่งที่เกิดขึ้นในรหัสคือ:
MyServiceProvider.$get(); // return the instance of the service
เพื่อเรียกคืนอีกครั้งบริการจะเรียกโรงงานซึ่งเป็นวิธีการ $ get () ของผู้ให้บริการที่เกี่ยวข้อง ยิ่งไปกว่านั้น $ injector.instantiate () เป็นวิธีการที่เรียก Object.create () ในท้ายที่สุดด้วยฟังก์ชั่นคอนสตรัค นั่นเป็นเหตุผลที่เราใช้ "สิ่งนี้" ในบริการ
สำหรับ ES5 นั้นไม่สำคัญว่าเราจะใช้อะไร: บริการ () หรือโรงงาน () มันเป็นโรงงานที่ถูกเรียกเสมอซึ่งสร้างผู้ให้บริการสำหรับบริการของเรา
คุณสามารถทำสิ่งเดียวกันกับบริการได้เช่นกัน บริการเป็นฟังก์ชั่นคอนสตรัคเตอร์ที่ไม่ได้ป้องกันเราจากการคืนค่าตัวอักษรวัตถุ ดังนั้นเราสามารถใช้รหัสบริการของเราและเขียนมันในลักษณะที่มันทำสิ่งเดียวกันกับโรงงานของเราหรือในคำอื่น ๆ คุณสามารถเขียนบริการเป็นโรงงานเพื่อส่งคืนวัตถุ
ทำไมคนส่วนใหญ่แนะนำให้ใช้โรงงานมากกว่าบริการ นี่คือคำตอบที่ดีที่สุดที่ฉันเคยเห็นซึ่งมาจากหนังสือของ Pawel Kozlowski: Mastering Web Application Development กับ AngularJS
วิธีการจากโรงงานเป็นวิธีที่พบได้บ่อยที่สุดในการนำวัตถุเข้าสู่ระบบการฉีดขึ้นรูปของ AngularJS มีความยืดหยุ่นสูงและมีตรรกะการสร้างที่ซับซ้อน เนื่องจากโรงงานเป็นหน้าที่ปกติเรายังสามารถใช้ประโยชน์จากขอบเขตศัพท์ใหม่เพื่อจำลองตัวแปร "ส่วนตัว" สิ่งนี้มีประโยชน์มากเพราะเราสามารถซ่อนรายละเอียดการใช้งานของบริการที่กำหนดได้ "