การผกผันของการควบคุม vs การพึ่งพาการฉีด


525

จากบทความที่เขียนโดย Martin Fowlerการผกผันของการควบคุมเป็นหลักการที่ผังการควบคุมของโปรแกรมกลับด้าน: แทนที่จะให้โปรแกรมเมอร์ควบคุมการไหลของโปรแกรมแหล่งภายนอก (กรอบงานบริการส่วนประกอบอื่น ๆ ) เข้าควบคุม มัน. มันเหมือนกับว่าเราเสียบบางสิ่งเข้ากับสิ่งอื่น เขาพูดถึงตัวอย่างเกี่ยวกับ EJB 2.0:

ตัวอย่างเช่นอินเทอร์เฟซเซสชัน Bean กำหนด ejbRemove, ejbPassivate (เก็บไว้ในที่เก็บรอง) และ ejbActivate (คืนค่าจากสถานะแฝง) คุณไม่สามารถควบคุมได้เมื่อมีการเรียกใช้เมธอดเหล่านี้ว่าทำอะไร ภาชนะโทรหาเราเราไม่เรียกมันว่า

สิ่งนี้นำไปสู่ความแตกต่างระหว่างเฟรมเวิร์กและไลบรารี:

Inversion of Control เป็นส่วนสำคัญของสิ่งที่ทำให้เฟรมเวิร์กแตกต่างจากไลบรารี ไลบรารีเป็นชุดของฟังก์ชั่นที่คุณสามารถโทรหาได้ในปัจจุบันมักจัดเป็นคลาส การโทรแต่ละครั้งจะทำงานและส่งคืนการควบคุมให้กับลูกค้า

ฉันคิดว่ามุมมองที่ DI คือ IOC หมายถึงการพึ่งพาของวัตถุที่มีการคว่ำ: แทนที่จะควบคุมการพึ่งพาของตัวเองวงจรชีวิต ... สิ่งอื่นทำเพื่อคุณ แต่อย่างที่คุณบอกฉันเกี่ยวกับ DI ด้วยมือ DI ไม่จำเป็นต้องเป็น IOC เรายังสามารถมี DI และไม่มี IOC

อย่างไรก็ตามในบทความนี้ (จาก pococapsule, IOC Framework อื่นสำหรับ C / C ++), มันแสดงให้เห็นว่าเนื่องจาก IOC และ DI, คอนเทนเนอร์ IOC และกรอบ DI นั้นดีกว่า J2EE มากเนื่องจาก J2EE ผสมรหัสเฟรมเวิร์กเข้ากับส่วนประกอบ จึงไม่ทำให้เป็นวัตถุ Java / C ++ ธรรมดาเก่า (POJO / POCO)

ผกผันของการควบคุมบรรจุภัณฑ์นอกเหนือจากรูปแบบการฉีดพึ่งพา (ลิงค์ถาวร)

การอ่านเพิ่มเติมเพื่อทำความเข้าใจว่ามีปัญหาอะไรกับ Component-Based Development Framework เก่าซึ่งนำไปสู่บทความที่สองข้างต้น: ทำไมและสิ่งใดของ Inversion of Control (ลิงก์ถาวร)

คำถามของฉัน : IOC และ DI คืออะไร ฉันสับสน. ขึ้นอยู่กับ pococapsule, IOC เป็นสิ่งที่สำคัญกว่าการกลับกันของการควบคุมระหว่างวัตถุหรือโปรแกรมเมอร์และกรอบ


2
นี่เป็นบทความที่ดีเกี่ยวกับ IoC กับ DI (Dependency Inject) vs SL (ตัวระบุบริการ): tinyurl.com/kk4be58 - สารสกัดจาก url: IoC กับ DI (Dependency Injection)? IoC เป็นแนวคิดทั่วไปที่ควบคุมการไหลของกลับจากรหัสลูกค้าไปยังกรอบซึ่ง "ทำอะไรบางอย่างสำหรับลูกค้า" SL (Service Locator) และ DI (Dependency Injection) เป็นสองรูปแบบการออกแบบที่เกิดจาก IoC
Swab.Jat

เพื่อเพิ่มสองเซ็นต์ของฉันถ้าใครสนใจว่าการฉีดพึ่งพาจะมีประโยชน์ในชุดรูปแบบร้านกาแฟฉันได้เขียนบทความเกี่ยวกับที่นี่: digigene.com/design-patterns/dependency-injection-coffeeshop
Ali Nem

3
บทความที่ดีสำหรับผู้เริ่มต้นasimplify.com/dependency-injection-inversion-control
Khawaja Asim

การพึ่งพาอาศัยการผกผัน: ขึ้นอยู่กับ abstractions ไม่ใช่ concretions การผกผันของการควบคุม: Main vs Abstraction และ Main เป็นกาวของระบบอย่างไร เหล่านี้คือบางส่วนที่ดีโพสต์พูดคุยเกี่ยวกับเรื่องนี้: coderstower.com/2019/03/26/... coderstower.com/2019/04/02/... coderstower.com/2019/04/09/...
แดเนียลแอนเดรส Pelaez โลเปซ

อ่านเกี่ยวกับเรื่องนี้ลึกมันจะล้างmartinfowler.com/articles/…
Dushman

คำตอบ:


644

IoCเป็นคำศัพท์ทั่วไปที่มีความหมายมากกว่าให้แอปพลิเคชันเรียกใช้เมธอดในเฟรมเวิร์กเรียกการประยุกต์ใช้โดยแอพพลิเคชั่น

DIเป็นรูปแบบของ IoC ซึ่งการใช้งานจะถูกส่งผ่านเข้าไปในวัตถุผ่านคอนสตรัคเตอร์ / เซ็ตเตอร์ / การค้นหาบริการซึ่งวัตถุจะ 'ขึ้นอยู่กับ' เพื่อให้ทำงานได้อย่างถูกต้อง

IoC โดยไม่ใช้ DIตัวอย่างเช่นจะเป็นรูปแบบเทมเพลตเนื่องจากการใช้งานสามารถเปลี่ยนแปลงได้ผ่านการจัดกลุ่มย่อยเท่านั้น

DI Frameworksได้รับการออกแบบให้ใช้งาน DI และสามารถกำหนดอินเตอร์เฟส (หรือคำอธิบายประกอบใน Java) เพื่อให้ง่ายต่อการส่งผ่านในการนำไปใช้งาน

IoC Containersเป็น DI Framework ที่สามารถทำงานนอกภาษาการเขียนโปรแกรม ในบางคุณสามารถกำหนดค่าการใช้งานที่จะใช้ในไฟล์เมตาดาต้า (เช่น XML) ซึ่งเป็นที่บุกรุกน้อย มีบางส่วนที่คุณสามารถทำ IoC ที่ปกติจะเป็นไปไม่ได้เช่นเดียวกับการดำเนินการฉีดที่pointcuts

ดูเพิ่มเติมนี้บทความของมาร์ตินฟาวเลอร์


2
ขอบคุณสำหรับคำตอบ. แต่บทความอื่นแสดงให้เห็นว่าด้วย IOC คอนเทนเนอร์ IOC นั้นเหนือกว่า EJB มากกว่าในขณะที่ Martin Fowler แนะนำว่า EJB เป็นตัวอย่างทั่วไปของ IOC
Amumu

5
การจัดการ EJB เป็นตัวอย่างทั่วไปของ IoC คุณสามารถเห็นได้จากข้อเท็จจริงที่ว่าวงจรชีวิตของ EJB ได้รับการจัดการโดยคอนเทนเนอร์ไม่ใช่โดยโปรแกรมเมอร์ โปรแกรมเมอร์ไม่สร้างหรือทำลายตัวอย่าง EJB เพราะควบคุมจะได้รับการแต่งตั้งไปยังเซิร์ฟเวอร์ นั่นคือแนวคิดของ IoC: รหัสภายนอกจะควบคุมเมื่อรหัสของคุณถูกเรียกซึ่งมักจะเป็นสิ่งที่ตรงกันข้ามกับสิ่งที่มันทำไปเกือบตลอดเวลา
brandizzi

2
IoC เป็นคำทั่วไปที่มีความหมายมากกว่าการให้แอปพลิเคชันเรียกใช้วิธีการในเฟรมเวิร์กเรียกการใช้งานที่จัดเตรียมโดยแอ็พพลิเคชัน คุณช่วยอธิบายเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ไหม?
Imad Alazani

21
หลักการของ Aka Hollywoodอย่าโทรหาเราเราจะโทรหาคุณ ปล่อยให้การเรียกใช้ขึ้นอยู่กับกรอบงานแทนแอปพลิเคชัน
Garrett Hall

@ImadAlazani คุณควรอ่านบทความที่ Garrett แนบมาซึ่งเป็นการอภิปรายโดยละเอียดเกี่ยวกับการเปลี่ยนการควบคุมจากรหัสแอปพลิเคชันไปเป็นเฟรมเวิร์ก
MengT

210

กล่าวโดยย่อ IoC เป็นคำที่กว้างกว่ามากซึ่งรวมถึง แต่ไม่ จำกัด เพียง DI

คำว่า Inversion of Control (IoC) เดิมหมายถึงรูปแบบการเขียนโปรแกรมใด ๆ ที่กรอบงานโดยรวมหรือเวลาทำงานควบคุมการไหลของโปรแกรม

ก่อนที่ DI จะมีชื่อผู้คนเริ่มที่จะอ้างถึงเฟรมเวิร์กที่จัดการ Dependencies เป็น Inversion of Control Containers และในไม่ช้าความหมายของ IoC ค่อย ๆ ล่องลอยไปสู่ความหมายเฉพาะนั้น ๆ : Inversion of Control for Dependencies

การผกผันของการควบคุม (IoC) หมายความว่าวัตถุไม่ได้สร้างวัตถุอื่น ๆ ที่พวกเขาต้องพึ่งพาการทำงานของพวกเขา แต่จะได้รับวัตถุที่ต้องการจากแหล่งภายนอก (ตัวอย่างเช่นไฟล์กำหนดค่า xml)

Dependency Injection (DI) หมายถึงการทำสิ่งนี้โดยปราศจากการแทรกแซงของวัตถุโดยปกติจะเป็นส่วนประกอบเฟรมเวิร์กที่ส่งผ่านพารามิเตอร์คอนสตรัคเตอร์และคุณสมบัติชุด


1
ดูเหมือนว่า IoC เป็นเพียงคำศัพท์หนึ่งสำหรับหลักการการพึ่งพิงการพึ่งพาใช่หรือไม่?
ทอดด์แวนซ์

@ToddVance - ใช่ฉันคิดว่า IoC และ DIP เป็นแบบเดียวกัน DIP และ DI นั้นไม่เหมือนกัน IoC สามารถทำได้โดยไม่มี DI แต่ DI ไม่สามารถทำได้โดยไม่ใช้ IoC
Eljay

2
@ToddVance - ไม่ DIP และ IoC ไม่ใช่คำพ้องความหมายและไม่เกี่ยวข้องกัน
TSmith

3
ฮ่านั่นคือเหตุผลที่ฉันมาที่นี่ในหัวข้อนี้ ... "การกลับกันของการควบคุมเทียบกับการพึ่งพาการฉีด"
ทอดด์แวนซ์

50

ป้อนคำอธิบายรูปภาพที่นี่
แหล่ง

IoC ( I nversion o f C ontrol): - มันเป็นคำศัพท์ทั่วไปและนำไปใช้ในหลายวิธี (เหตุการณ์ผู้ได้รับมอบหมาย ฯลฯ )

DI ( D ependency ฉัน njection): - DI เป็นประเภทย่อยของ IoC และมีการดำเนินการโดยการฉีดตัวสร้างฉีดหมาหรือฉีดอินเตอร์เฟซ

แต่ Spring รองรับเฉพาะสองประเภทต่อไปนี้:

  • Setter Injection
    • Setter-based DI ถูกรับรู้โดยการเรียกเมธอด setter บน beans ของผู้ใช้หลังจากเรียกใช้ตัวสร้างแบบไม่มีอาร์กิวเมนต์หรือเมธอดสแตติกโรงงานแบบไม่มีอาร์กิวเมนต์เพื่อสร้างอินสแตนซ์ bean ของตน
  • ตัวสร้างการฉีด
    • Constructor-based DI ได้รับการยอมรับโดยการเรียกนวกรรมิกที่มีข้อโต้แย้งจำนวนมากซึ่งแต่ละอันเป็นตัวแทนของผู้ทำงานร่วมกันการใช้สิ่งนี้เราสามารถตรวจสอบได้ว่าถั่วที่ถูกฉีดนั้นไม่ได้เป็นโมฆะและล้มเหลวอย่างรวดเร็ว NullPointerException: bean does not existขณะที่เริ่มต้นการประยุกต์ใช้ตัวเองที่เราได้รับ คอนสตรัคเตอร์แบบฉีดเป็นการปฏิบัติที่ดีที่สุดในการฉีดการพึ่งพา

1
มันไม่ถูกต้องที่ระบุว่า Spring ไม่สนับสนุนการฉีดคุณสมบัติ มันทำ และมันก็เป็นการปฏิบัติที่ไม่ดีฉันเห็นด้วย
kekko12

คำอธิบายประกอบ Spring @Autowired เป็นวิธีการฉีดคุณสมบัติในความคิดของฉัน
Sajith

49

DI เป็นส่วนย่อยของ IoC

  • IoCหมายความว่าวัตถุไม่ได้สร้างวัตถุอื่น ๆ ที่พวกเขาต้องพึ่งพาการทำงานของพวกเขา แต่จะรับวัตถุที่ต้องการจากบริการภายนอก (ตัวอย่างเช่นไฟล์ xml หรือบริการแอปเดียว) การใช้งาน IoC 2 ครั้งฉันใช้คือ DI และ ServiceLocator
  • DIหมายถึงหลักการของ IoC ในการทำให้วัตถุที่อ้างถึงทำโดยไม่ใช้วัตถุที่เป็นรูปธรรม แต่เป็นนามธรรม (อินเตอร์เฟส) สิ่งนี้ทำให้ห่วงโซ่ส่วนประกอบทั้งหมดสามารถทดสอบได้ทำให้ส่วนประกอบระดับสูงขึ้นไม่ได้ขึ้นอยู่กับส่วนประกอบระดับล่างเท่านั้นจากส่วนต่อประสาน Mocks ใช้อินเตอร์เฟสเหล่านี้

นี่คือบางส่วนเทคนิคอื่น ๆ เพื่อให้บรรลุ IoC


ฉันจะไม่พูดว่า IoC หมายถึงไม่สร้างวัตถุ เมื่อคุณเรียกใช้เมธอดคลาสไม่ได้โดยตรง แต่เป็นวิธีการอินเทอร์เฟซ - นี่คือการผกผันของการควบคุม (ในกรณีนี้ผู้โทรไม่ได้ขึ้นอยู่กับการเรียกรหัส) และมันไม่เกี่ยวข้องกับการสร้างวัตถุเลย อีกตัวอย่างหนึ่งของ IoC คือกิจกรรมและผู้ได้รับมอบหมาย
Eugene Gorbovoy

19

เนื่องจากคำตอบทั้งหมดเน้นที่ทฤษฎีฉันจึงต้องการสาธิตด้วยวิธีแรก:

สมมติว่าเรากำลังสร้างแอปพลิเคชันที่มีคุณสมบัติในการส่งข้อความยืนยัน SMS เมื่อมีการส่งคำสั่งซื้อ เราจะมีสองคลาสหนึ่งมีหน้าที่ส่ง SMS (SMSService) และอีกหนึ่งรับผิดชอบในการจับภาพอินพุตผู้ใช้ (UIHandler) รหัสของเราจะมีลักษณะดังนี้:

public class SMSService
{
    public void SendSMS(string mobileNumber, string body)
    {
        SendSMSUsingGateway(mobileNumber, body);
    }

    private void SendSMSUsingGateway(string mobileNumber, string body)
    {
        /*implementation for sending SMS using gateway*/
    }
}

public class UIHandler
{
    public void SendConfirmationMsg(string mobileNumber)
    {
        SMSService _SMSService = new SMSService();
        _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
    }
}

การใช้งานข้างต้นไม่ผิด แต่มีปัญหาเล็กน้อย:
-) สมมติว่าในสภาพแวดล้อมการพัฒนาคุณต้องการบันทึก SMS ที่ส่งไปยังไฟล์ข้อความแทนที่จะใช้ SMS เกตเวย์เพื่อให้บรรลุสิ่งนี้; เราจะสิ้นสุดการเปลี่ยนแปลงการใช้งานอย่างเป็นรูปธรรมของ (SMSService) ด้วยการใช้งานอื่นเรากำลังสูญเสียความยืดหยุ่นและถูกบังคับให้เขียนรหัสใหม่ในกรณีนี้
-) เราจะจบการผสมความรับผิดชอบของคลาส (UIHandler) ของเราไม่ควรรู้เกี่ยวกับการใช้งานอย่างเป็นรูปธรรมของ (SMSService) สิ่งนี้ควรทำนอกห้องเรียนโดยใช้ "อินเทอร์เฟซ" เมื่อสิ่งนี้ถูกนำมาใช้มันจะทำให้เราสามารถเปลี่ยนพฤติกรรมของระบบโดยการแลกเปลี่ยน (SMSService) ที่ใช้กับบริการจำลองอื่นซึ่งใช้อินเทอร์เฟซเดียวกันบริการนี้จะบันทึก SMS เป็นไฟล์ข้อความแทนที่จะส่งไปยัง mobileNumber

ในการแก้ไขปัญหาข้างต้นเราใช้ส่วนต่อประสานซึ่งจะดำเนินการโดย (SMSService) และใหม่ (MockSMSService) โดยทั่วไปอินเทอร์เฟซใหม่ (ISMSService) จะเปิดเผยพฤติกรรมเดียวกันของบริการทั้งสองตามรหัสด้านล่าง:

public interface ISMSService
{
    void SendSMS(string phoneNumber, string body);
}

จากนั้นเราจะเปลี่ยนการใช้งาน (SMSService) เพื่อใช้อินเทอร์เฟซ (ISMSService):

public class SMSService : ISMSService
{
    public void SendSMS(string mobileNumber, string body)
    {
        SendSMSUsingGateway(mobileNumber, body);
    }

    private void SendSMSUsingGateway(string mobileNumber, string body)
    {
        /*implementation for sending SMS using gateway*/
        Console.WriteLine("Sending SMS using gateway to mobile: 
        {0}. SMS body: {1}", mobileNumber, body);
    }
}

ตอนนี้เราจะสามารถสร้างบริการจำลองใหม่ (MockSMSService) ด้วยการใช้งานที่แตกต่างกันโดยสิ้นเชิงโดยใช้อินเทอร์เฟซเดียวกัน:

public class MockSMSService :ISMSService
{
    public void SendSMS(string phoneNumber, string body)
    {
        SaveSMSToFile(phoneNumber,body);
    }

    private void SaveSMSToFile(string mobileNumber, string body)
    {
        /*implementation for saving SMS to a file*/
        Console.WriteLine("Mocking SMS using file to mobile: 
        {0}. SMS body: {1}", mobileNumber, body);
    }
}

ณ จุดนี้เราสามารถเปลี่ยนรหัสใน (UIHandler) เพื่อใช้การดำเนินการที่เป็นรูปธรรมของบริการ (MockSMSService) ได้อย่างง่ายดายดังนี้:

public class UIHandler
{
    public void SendConfirmationMsg(string mobileNumber)
    {
        ISMSService _SMSService = new MockSMSService();
        _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
    }
}

เราได้รับความยืดหยุ่นจำนวนมากและมีการแยกข้อกังวลในรหัสของเรา แต่เรายังจำเป็นต้องทำการเปลี่ยนแปลงรหัสฐานเพื่อสลับไปมาระหว่างบริการ SMS ทั้งสอง ดังนั้นเราจึงจำเป็นต้องใช้การพึ่งพาการฉีด

เพื่อให้บรรลุสิ่งนี้เราต้องดำเนินการเปลี่ยนแปลงตัวสร้างคลาสของเรา (UIHandler) เพื่อส่งผ่านการพึ่งพาผ่านโดยการทำเช่นนี้รหัสที่ใช้ (UIHandler) สามารถกำหนดว่าการใช้งานที่เป็นรูปธรรมของ (ISMSService) คืออะไร:

public class UIHandler
{
    private readonly ISMSService _SMSService;

    public UIHandler(ISMSService SMSService)
    {
        _SMSService = SMSService;
    }

    public void SendConfirmationMsg(string mobileNumber)
    {
        _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
    }
}

ตอนนี้รูปแบบ UI ที่จะพูดคุยกับคลาส (UIHandler) มีหน้าที่รับผิดชอบในการส่งผ่านการใช้งานอินเตอร์เฟส (ISMSService) ใด ซึ่งหมายความว่าเราได้ควบคุมการกลับรายการ (UIHandler) จะไม่รับผิดชอบในการตัดสินใจว่าจะใช้งานสิ่งใดอีกการใช้รหัสการโทรทำได้ เราได้นำหลักการผกผันของการควบคุมซึ่ง DI เป็นประเภทหนึ่ง

รหัสรูปแบบ UI จะเป็นดังนี้:

class Program
{
    static void Main(string[] args)
    {
        ISMSService _SMSService = new MockSMSService(); // dependency

        UIHandler _UIHandler = new UIHandler(_SMSService);
        _UIHandler.SendConfirmationMsg("96279544480");

        Console.ReadLine();
    }
}

คำอธิบายที่ดี
ZiviMagic

19

IOC (Inversion Of Control) : ให้การควบคุมคอนเทนเนอร์เพื่อรับอินสแตนซ์ของวัตถุที่เรียกว่า Inversion of Control หมายถึงแทนที่จะสร้างวัตถุโดยใช้โอเปอเรเตอร์ใหม่ปล่อยให้คอนเทนเนอร์ทำเช่นนั้นกับคุณ

DI (Dependency Injection) : วิถีฉีดคุณสมบัติไปยังวัตถุที่เรียกว่าการพึ่งพาการฉีด

เรามีการพึ่งพาการฉีดสามประเภท:

  1. ตัวสร้างการฉีด
  2. Setter / Getter Injection
  3. อินเตอร์เฟสการฉีด

สปริงรองรับConstructor InjectionและSetter / Getter Injectionเท่านั้น


5

แต่เอกสารฤดูใบไม้ผลิบอกว่ามันเหมือนกัน

http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-introduction

ในบรรทัดแรก " IoC ยังเป็นที่รู้จักกันในนามการฉีดพึ่งพา (DI) "


1
ฉันเดาว่าสิ่งที่พวกเขาพยายามพูดถึงคือ DI เป็นรูปแบบการออกแบบที่ใช้กันอย่างแพร่หลายของ IoC ที่สามารถเรียกได้ง่ายว่า IoC aka DI - เว้นแต่เอกสารจะมีการอ้างอิงที่ชัดเจนที่แนะนำเป็นอย่างอื่น
ha9u63ar

5
"IoC ยังเป็นที่รู้จักกันในนามฉีดพึ่งพา (DI)" ... นักขี่ม้า!
MikeM

5

IoC - การผกผันของการควบคุมเป็นศัพท์ทั่วไปไม่ขึ้นกับภาษาจริงๆแล้วมันไม่ได้สร้างวัตถุ แต่อธิบายว่าวัตถุใดที่กำลังสร้าง

DI - Dependency Injection เป็นคำที่เป็นรูปธรรมซึ่งเราให้การพึ่งพาของวัตถุในขณะดำเนินการโดยใช้เทคนิคการฉีดที่แตกต่างกัน ได้แก่ Setter Injection, Constructor Injection หรือ Interface Injection


4

การผกผันของการควบคุมเป็นกระบวนทัศน์การออกแบบโดยมีเป้าหมายในการให้การควบคุมเพิ่มเติมกับส่วนประกอบเป้าหมายของแอปพลิเคชันของคุณ
การขึ้นต่อกันของการพึ่งพาเป็นรูปแบบที่ใช้ในการสร้างอินสแตนซ์ของวัตถุที่วัตถุอื่นพึ่งพาโดยไม่รู้ตัว ณ เวลารวบรวมซึ่งจะใช้คลาสใดในการทำหน้าที่นั้น

มีเทคนิคพื้นฐานหลายประการในการนำการควบคุมกลับกัน เหล่านี้คือ:

  • ใช้รูปแบบจากโรงงาน
  • การใช้รูปแบบตัวระบุตำแหน่งบริการ
  • ใช้การฉีดพึ่งพาใด ๆ ที่ระบุด้านล่างประเภท:

    1) คอนสตรัคเตอร์ฉีด
    2) การตั้งค่าการฉีด
    3) อินเทอร์เฟซการฉีด

4

DIและIOCเป็นรูปแบบการออกแบบสองแบบที่มุ่งเน้นไปที่การให้คัปปลิ้งแบบหลวม ๆ ระหว่างส่วนประกอบหรือเป็นวิธีที่เราแยกความสัมพันธ์แบบพึ่งพาระหว่างวัตถุเพื่อให้วัตถุไม่แน่นซึ่งกันและกัน

จากตัวอย่างต่อไปนี้ฉันพยายามอธิบายทั้งแนวคิดเหล่านี้

ก่อนหน้านี้เรากำลังเขียนโค้ดแบบนี้

Public MyClass{
 DependentClass dependentObject
 /*
  At somewhere in our code we need to instantiate 
  the object with new operator  inorder to use it or perform some method.
  */ 
  dependentObject= new DependentClass();
  dependentObject.someMethod();
}

ด้วยการฉีดพึ่งพาพึ่งพาหัวฉีดจะดูแล instantiation ของวัตถุ

Public MyClass{
 /* Dependency injector will instantiate object*/
 DependentClass dependentObject

 /*
  At somewhere in our code we perform some method. 
  The process of  instantiation will be handled by the dependency injector
 */ 

  dependentObject.someMethod();
}

กระบวนการข้างต้นในการให้การควบคุมแก่ผู้อื่น (ตัวอย่างเช่นคอนเทนเนอร์) สำหรับการสร้างอินสแตนซ์และการฉีดสามารถเรียกได้ว่าเป็น Inversion of Control และกระบวนการที่คอนเทนเนอร์ IOC ฉีดการพึ่งพาสำหรับเรานั้นสามารถเรียกได้ว่าเป็นการพึ่งพาการฉีด

IOC เป็นหลักการที่ควบคุมการไหลของโปรแกรมกลับหัว: แทนที่จะเป็นโปรแกรมเมอร์ที่ควบคุมการไหลของโปรแกรมโปรแกรมควบคุมการไหลโดยการลดโอเวอร์เฮดไปยังโปรแกรมเมอร์และกระบวนการที่ใช้โดยโปรแกรมในการฉีดพึ่งพานั้นเรียกว่า DI

แนวคิดทั้งสองทำงานร่วมกันทำให้เรามีวิธีการเขียนโค้ดที่ยืดหยุ่นนำกลับมาใช้ใหม่ได้และห่อหุ้มมากขึ้นซึ่งทำให้พวกเขาเป็นแนวคิดที่สำคัญในการออกแบบโซลูชันเชิงวัตถุ

ยังแนะนำให้อ่าน

การฉีดพึ่งพาคืออะไร?

คุณสามารถตรวจสอบคำตอบที่คล้ายกันของฉันที่นี่

ความแตกต่างระหว่าง Inversion of Control และ Dependency Injection


3

Inversion of Control เป็นหลักการออกแบบทั่วไปของสถาปัตยกรรมซอฟต์แวร์ที่ช่วยในการสร้างเฟรมเวิร์กซอฟต์แวร์แบบแยกส่วนที่สามารถนำมาใช้ซ้ำได้ซึ่งง่ายต่อการบำรุงรักษา

มันเป็นหลักการออกแบบที่การไหลของการควบคุมเป็น "ได้รับ" จากห้องสมุดที่เขียนทั่วไปหรือรหัสที่นำมาใช้ใหม่

เพื่อให้เข้าใจได้ดีขึ้นให้ดูว่าเราใช้รหัสอย่างไรในการเข้ารหัสก่อนหน้านี้ ในขั้นตอน / ภาษาดั้งเดิมตรรกะทางธุรกิจโดยทั่วไปจะควบคุมการไหลของแอปพลิเคชันและ "โทร" รหัสหรือฟังก์ชั่นทั่วไปหรือนำกลับมาใช้ซ้ำได้ ตัวอย่างเช่นในแอปพลิเคชันคอนโซลแบบง่ายโฟลว์การควบคุมของฉันถูกควบคุมโดยคำแนะนำของโปรแกรมของฉันซึ่งอาจรวมถึงการเรียกไปยังฟังก์ชั่นที่ใช้ซ้ำได้ทั่วไป

print ("Please enter your name:");
scan (&name);
print ("Please enter your DOB:");
scan (&dob);

//More print and scan statements
<Do Something Interesting>

//Call a Library function to find the age (common code)
print Age

ในทางตรงกันข้ามกับ IoC Frameworks เป็นรหัสที่สามารถใช้ซ้ำได้ซึ่งเรียกว่า "ตรรกะทางธุรกิจ"

ตัวอย่างเช่นในระบบที่ใช้ windows กรอบจะพร้อมใช้งานเพื่อสร้างองค์ประกอบ UI เช่นปุ่มเมนูหน้าต่างและกล่องโต้ตอบ เมื่อฉันเขียนตรรกะทางธุรกิจของแอปพลิเคชันของฉันมันจะเป็นเหตุการณ์ของเฟรมเวิร์กที่จะเรียกรหัสตรรกะทางธุรกิจของฉัน (เมื่อมีเหตุการณ์ถูกไล่ออก) และไม่ใช่สิ่งที่ตรงกันข้าม

แม้ว่ารหัสของเฟรมเวิร์กจะไม่ทราบถึงตรรกะทางธุรกิจของฉัน แต่ก็ยังคงรู้วิธีเรียกรหัสของฉัน นี่คือความสำเร็จโดยใช้เหตุการณ์ / ผู้ได้รับมอบหมายการเรียกกลับ ฯลฯ นี่คือการควบคุมการไหลของ "Inverted"

ดังนั้นแทนที่จะขึ้นอยู่กับการไหลของการควบคุมบนวัตถุที่ถูกผูกไว้แบบคงที่การไหลขึ้นอยู่กับกราฟวัตถุโดยรวมและความสัมพันธ์ระหว่างวัตถุต่าง ๆ

Dependency Injection เป็นรูปแบบการออกแบบที่ใช้หลักการ IoC สำหรับการแก้ไขการพึ่งพาของวัตถุ

ในคำที่ง่ายกว่าเมื่อคุณพยายามเขียนโค้ดคุณจะสร้างและใช้คลาสที่แตกต่างกัน หนึ่งคลาส (Class A) อาจใช้คลาสอื่น (Class B และ / หรือ D) ดังนั้นคลาส B และ D จึงขึ้นกับคลาส A

การเปรียบเทียบง่ายๆจะเป็นรถคลาส รถอาจขึ้นอยู่กับชั้นเรียนอื่น ๆ เช่นเครื่องยนต์ยางรถยนต์และอื่น ๆ

การฉีดพึ่งพาแสดงให้เห็นว่าแทนที่จะเป็นคลาส Dependent (Class Car ที่นี่) เพื่อสร้างการพึ่งพา (Class Engine และคลาสยาง) คลาสควรถูกฉีดด้วยอินสแตนซ์ที่เป็นรูปธรรมของการพึ่งพา

ให้เข้าใจด้วยตัวอย่างที่เป็นประโยชน์มากขึ้น พิจารณาว่าคุณกำลังเขียน TextEditor ของคุณเอง เหนือสิ่งอื่นใดคุณสามารถมีเครื่องตรวจการสะกดคำที่ให้ความสะดวกแก่ผู้ใช้ในการตรวจสอบความผิดพลาดในข้อความของเขา การติดตั้งโค้ดอย่างง่ายสามารถ:

Class TextEditor
{

    //Lot of rocket science to create the Editor goes here

    EnglishSpellChecker objSpellCheck;
    String text;

    public void TextEditor()

    {   

        objSpellCheck = new EnglishSpellChecker();

    }

    public ArrayList <typos> CheckSpellings()
    {

        //return Typos;

    }

}

ตั้งแต่แรกเห็นทุกคนดูเป็นสีดอกกุหลาบ ผู้ใช้จะเขียนข้อความ ผู้พัฒนาจะจับข้อความและเรียกใช้ฟังก์ชัน CheckSpellings และจะพบรายการ Typos ที่เขาจะแสดงต่อผู้ใช้

ดูเหมือนว่าทุกอย่างจะทำงานได้ดีจนกระทั่งวันหนึ่งเมื่อผู้ใช้คนหนึ่งเริ่มเขียนภาษาฝรั่งเศสในเครื่องมือแก้ไข

เพื่อให้การสนับสนุนสำหรับภาษาอื่น ๆ เราจำเป็นต้องมี SpellCheckers มากขึ้น อาจเป็นภาษาฝรั่งเศสเยอรมันสเปนและอื่น ๆ

ที่นี่เราได้สร้างรหัสที่คู่กันอย่างแน่นหนาด้วย "SpellChecker" ภาษาอังกฤษ "ที่ถูกผนวกเข้ากับคลาส TextEditor ของเราอย่างแน่นหนาซึ่งหมายความว่าคลาส TextEditor ของเรานั้นขึ้นอยู่กับ EnglishSpellChecker หรือกล่าวอีกนัยหนึ่ง EnglishSpellCheker เราจำเป็นต้องลบการอ้างอิงนี้ เพิ่มเติมเครื่องมือแก้ไขข้อความของเราต้องการวิธีการอ้างอิงที่เป็นรูปธรรมของ Spell Checker ใด ๆ ตามดุลยพินิจของนักพัฒนาในขณะใช้งาน

ดังนั้นอย่างที่เราเห็นในการแนะนำ DI มันแสดงให้เห็นว่าชั้นควรถูกฉีดด้วยการพึ่งพา ดังนั้นจึงเป็นความรับผิดชอบของรหัสโทรศัพท์ในการฉีดการอ้างอิงทั้งหมดไปยังคลาส / รหัสที่เรียกว่า ดังนั้นเราสามารถปรับโครงสร้างรหัสของเราเป็น

interface ISpellChecker
{

    Arraylist<typos> CheckSpelling(string Text);

}

Class EnglishSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}



Class FrenchSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}

ในตัวอย่างของเราคลาส TextEditor ควรรับอินสแตนซ์ที่เป็นรูปธรรมของชนิด ISpellChecker

ตอนนี้การพึ่งพาสามารถฉีดในตัวสร้างทรัพย์สินสาธารณะหรือวิธีการ

ให้ลองเปลี่ยนคลาสของเราโดยใช้ Constructor DI คลาส TextEditor ที่เปลี่ยนแปลงจะมีลักษณะดังนี้:

Class TextEditor

{

    ISpellChecker objSpellChecker;

    string Text;



    public void TextEditor(ISpellChecker objSC)

    {

        objSpellChecker = objSC;

    }



    public ArrayList <typos> CheckSpellings()

    {

        return objSpellChecker.CheckSpelling();

    }

}

เพื่อให้รหัสโทรในขณะที่สร้างตัวแก้ไขข้อความสามารถฉีด SpellChecker Type ที่เหมาะสมกับอินสแตนซ์ของ TextEditor

คุณสามารถอ่านบทความฉบับสมบูรณ์ได้ที่นี่


3

IOC (Inversion Of Control):การให้การควบคุมกับคอนเทนเนอร์เพื่อรับอินสแตนซ์ของวัตถุเรียกว่า Inversion of Control มันหมายถึงแทนที่จะสร้างวัตถุโดยใช้โอเปอเรเตอร์ใหม่ให้คอนเทนเนอร์ทำเพื่อคุณ

DI (Dependency Injection): การผ่านพารามิเตอร์ที่ต้องการ (คุณสมบัติ) จาก XML ไปยังวัตถุ (ใน POJO CLASS) เรียกว่า Dependency injection


2

IOCระบุว่าคลาสภายนอกที่จัดการคลาสของแอปพลิเคชันและคลาสภายนอกหมายถึงคอนเทนเนอร์ที่จัดการการพึ่งพาระหว่างคลาสของแอปพลิเคชัน แนวคิดพื้นฐานของIOCคือโปรแกรมเมอร์ไม่จำเป็นต้องสร้างวัตถุของคุณ แต่อธิบายว่าควรสร้างอย่างไร

งานหลักที่ดำเนินการโดยคอนเทนเนอร์ IoC คือ: เพื่อยกตัวอย่างคลาสแอปพลิเคชัน เพื่อกำหนดค่าวัตถุ เพื่อรวบรวมการพึ่งพาระหว่างวัตถุ

DIเป็นกระบวนการในการให้การอ้างอิงของวัตถุ ณ รันไทม์โดยใช้ setter injection หรือ constructor injection


2

IOC (Inversion of Control) เป็นแนวคิดการออกแบบรูปแบบการถอดการอ้างอิงและ decoupling พวกเขาเพื่อทำให้การไหลที่ไม่ใช่เชิงเส้นและปล่อยให้คอนเทนเนอร์ / หรือหน่วยงานอื่นจัดการการจัดสรรการพึ่งพา ตามหลักการของฮอลลีวูด“ อย่าโทรหาเราเราจะโทรหาคุณ” ดังนั้นสรุปความแตกต่าง

การผกผันของการควบคุม: - เป็นคำทั่วไปที่จะแยกการพึ่งพาและมอบหมายการจัดสรรของพวกเขาและสิ่งนี้สามารถดำเนินการได้หลายวิธี (เหตุการณ์ผู้ได้รับมอบหมาย ฯลฯ )

การพึ่งพาการฉีด: - DI เป็นประเภทย่อยของ IOC และดำเนินการโดยการฉีดคอนสตรัคเตอร์การฉีดเซทเทอร์หรือการฉีดเมธอด

บทความต่อไปนี้อธิบายสิ่งนี้อย่างเป็นระเบียบ

https://www.codeproject.com/Articles/592372/Dependency-Injection-DI-vs-Inversion-of-Control-IO


1

ฉันคิดว่าสามารถแสดงความคิดได้อย่างชัดเจนโดยไม่ต้องเข้าไปในวัชพืชเชิงวัตถุซึ่งดูเหมือนจะยุ่งเหยิงความคิด

// dependency injection
function doSomething(dependency) {
    // do something with your dependency
}

// in contrast to creating your dependencies yourself
function doSomething() {
    dependency = getDependencySomehow()
}

// inversion of control
application = makeApp(authenticate, handleRequest, sendResponse)
application.run(getRequest())

// in contrast to direct control or a "library" style
application = makeApp()
request = application.getRequest()

if (application.authenticate(request.creds)) {
    response = application.handleRequest(request)
    application.sendResponse(response)
}

หากคุณเอียงศีรษะและเหล่ตาคุณจะเห็นว่า DI เป็นการใช้งาน IoC โดยเฉพาะด้วยความกังวล แทนที่จะเป็นการฉีดแบบจำลองและพฤติกรรมลงในกรอบแอปพลิเคชันหรือการดำเนินการตามลำดับที่สูงกว่าคุณกำลังแทรกตัวแปรลงในฟังก์ชันหรือวัตถุ


0

เริ่มต้นด้วย D of SOLID และดู DI และ IoC จากหนังสือของ Scott Millett "Professional ASP.NET Design Patterns":

หลักการผกผันของการพึ่งพา (DIP)

กรมทรัพย์สินทางปัญญาคือทั้งหมดที่เกี่ยวกับการแยกชั้นเรียนของคุณจากการใช้งานที่เป็นรูปธรรมและมีพวกเขาขึ้นอยู่กับชั้นเรียนนามธรรมหรืออินเตอร์เฟซ มันส่งเสริมมนต์ของการเข้ารหัสไปยังส่วนต่อประสานมากกว่าการนำไปใช้ซึ่งเพิ่มความยืดหยุ่นภายในระบบโดยทำให้แน่ใจว่าคุณไม่ได้เชื่อมโยงอย่างแน่นหนากับการใช้งานเพียงครั้งเดียว

การพึ่งพาการฉีด (DI) และการผกผันของการควบคุม (IoC)

การเชื่อมโยงอย่างใกล้ชิดกับกรมทรัพย์สินทางปัญญาเป็นหลักการ DI และหลักการ IoC DIเป็นการกระทำของการจัดหาระดับต่ำหรือคลาสที่พึ่งพาผ่านตัวสร้างวิธีการหรือคุณสมบัติ ใช้ร่วมกับ DI คลาสที่ขึ้นต่อกันเหล่านี้สามารถกลับไปใช้อินเทอร์เฟซหรือคลาสที่เป็นนามธรรมซึ่งจะนำไปสู่ระบบที่เชื่อมต่อกันอย่างอิสระที่สามารถทดสอบได้และเปลี่ยนแปลงได้ง่าย

ในIoCการควบคุมการไหลของระบบกลับด้านเมื่อเปรียบเทียบกับการโปรแกรมแบบโพรซีเดอร์ ตัวอย่างของสิ่งนี้คือคอนเทนเนอร์ IoCซึ่งมีจุดประสงค์เพื่อฉีดบริการลงในรหัสลูกค้าโดยไม่ต้องมีรหัสลูกค้าที่ระบุการใช้งานที่เป็นรูปธรรม การควบคุมในอินสแตนซ์นี้ที่กำลังกลับด้านเป็นการกระทำของลูกค้าที่ได้รับบริการ

Millett, C (2010) รูปแบบการออกแบบ ASP.NET มืออาชีพ สำนักพิมพ์ไวลีย์ 7-8


0

// ICO, DI, 10 ปีก่อนนี่เป็นวิธี:

public class  AuditDAOImpl implements Audit{

    //dependency
    AuditDAO auditDAO = null;
        //Control of the AuditDAO is with AuditDAOImpl because its creating the object
    public AuditDAOImpl () {
        this.auditDAO = new AuditDAO ();
    }
}

ขณะนี้มีสปริง 3,4 หรือล่าสุดเหมือนด้านล่าง

public class  AuditDAOImpl implements Audit{

    //dependency

     //Now control is shifted to Spring. Container find the object and provide it. 
    @Autowired
    AuditDAO auditDAO = null;

}

โดยรวมแล้วการควบคุมกลับด้านจากแนวคิดแบบเก่าของรหัสคู่ไปยังกรอบงานเช่น Spring ซึ่งทำให้วัตถุพร้อมใช้งาน นั่นคือ IOC เท่าที่ฉันรู้และการพึ่งพาการฉีดเท่าที่คุณรู้เมื่อเราฉีดวัตถุที่ต้องพึ่งพาเข้าไปในวัตถุอื่นโดยใช้ Constructor หรือ setters การฉีดโดยทั่วไปหมายถึงการส่งผ่านเป็นอาร์กิวเมนต์ ในฤดูใบไม้ผลิเรามีการกำหนดค่าตาม XML และคำอธิบายประกอบที่เรากำหนด bean object และส่งต่อวัตถุที่ต้องพึ่งพาด้วยสไตล์คอนสตรัคเตอร์หรือเซ็ตเตอร์เตอร์


0

ฉันพบตัวอย่างที่ดีที่สุดในDzone.comซึ่งเป็นประโยชน์อย่างยิ่งที่จะเข้าใจความแตกต่างที่แท้จริงระหว่าง IOC และ DI

“ IoC คือเมื่อคุณมีคนอื่นสร้างวัตถุให้คุณ” ดังนั้นแทนที่จะเขียนคำหลัก "ใหม่" (ตัวอย่างเช่น MyCode c = new MyCode ()) ในรหัสของคุณวัตถุจะถูกสร้างขึ้นโดยบุคคลอื่น ปกติแล้ว 'บุคคลอื่น' นี้จะเรียกว่าเป็นคอนเทนเนอร์ IoC มันหมายความว่าเราส่งมอบ rrsponsibility (การควบคุม) ไปยังคอนเทนเนอร์เพื่อรับอินสแตนซ์ของวัตถุที่เรียกว่า Inversion of Control. หมายถึงแทนที่จะสร้างวัตถุโดยใช้ตัวดำเนินการใหม่ให้คอนเทนเนอร์ทำเพื่อคุณ

   DI(Dependency Injection):  Way of injecting properties to an object is 
   called 
  Dependency injection.
   We have three types of Dependency injection
    1)  Constructor Injection
    2)  Setter/Getter Injection
    3)  Interface Injection
   Spring will support only Constructor Injection and Setter/Getter Injection.

อ่านบทความเต็ม IOCและ อ่านบทความเต็ม DI


0

1) DI คือ Child-> obj ขึ้นอยู่กับ parent-obj คำกริยาขึ้นอยู่กับความสำคัญ 2) IOC คือ Child-> obj ดำเนินการภายใต้แพลตฟอร์ม แพลตฟอร์มที่สามารถเป็นโรงเรียน, วิทยาลัย, ชั้นเรียนเต้นรำ ดำเนินการที่นี่เป็นกิจกรรมที่มีความหมายที่แตกต่างกันภายใต้ผู้ให้บริการแพลตฟอร์มใด ๆ

ตัวอย่างการปฏิบัติ: `

//DI
child.getSchool();
//IOC
child.perform()// is a stub implemented by dance-school
child.flourish()// is a stub implemented by dance-school/school/

`

-AB


0

สำหรับคำถามนี้ฉันจะบอกว่าวิกินั้นให้คำอธิบายอย่างละเอียดและเข้าใจง่ายอยู่แล้ว ฉันจะพูดที่สำคัญที่สุดที่นี่

การใช้งาน IoC

ในการเขียนโปรแกรมเชิงวัตถุมีเทคนิคพื้นฐานหลายอย่างที่จะนำการควบคุมกลับกัน เหล่านี้คือ:

  1. การใช้รูปแบบที่ตั้งบริการการใช้การฉีดพึ่งพาเช่นการฉีดคอนสตรัคเตอร์การฉีดพารามิเตอร์ Setter injection การฉีดอินเตอร์เฟส
  2. การใช้การค้นหาเชิงบริบท
  3. ใช้รูปแบบการออกแบบวิธีการแม่แบบ;
  4. ใช้รูปแบบการออกแบบกลยุทธ์

สำหรับการฉีดพึ่งพา

การฉีดพึ่งพาเป็นเทคนิคที่วัตถุหนึ่ง (หรือวิธีการแบบคงที่) หน้า ๆ การพึ่งพาของวัตถุอื่น การพึ่งพาเป็นวัตถุที่สามารถใช้ (บริการ) การฉีดเป็นการส่งผ่านของการอ้างอิงไปยังวัตถุที่อ้างถึง (ไคลเอนต์) ที่จะใช้


0

แนวคิด IoC เริ่มได้ยินในช่วงยุคการเขียนโปรแกรมขั้นตอน ดังนั้นจากบริบททางประวัติศาสตร์ IoC พูดคุยเกี่ยวกับการผกผันของความเป็นเจ้าของของการควบคุมการไหลคือผู้ที่มีความรับผิดชอบในการเรียกใช้ฟังก์ชั่นในลำดับที่ต้องการ - ไม่ว่าจะเป็นฟังก์ชั่นของตัวเอง

อย่างไรก็ตามเมื่อ OOP ปรากฏตัวผู้คนเริ่มพูดคุยเกี่ยวกับ IoC ในบริบทของ OOP ที่แอปพลิเคชันเกี่ยวข้องกับการสร้างวัตถุและความสัมพันธ์ของพวกเขาด้วยนอกเหนือจากการควบคุมการไหล แอปพลิเคชันดังกล่าวต้องการคว่ำความเป็นเจ้าของการสร้างวัตถุ (แทนการควบคุมการไหล) และต้องการคอนเทนเนอร์ที่รับผิดชอบการสร้างวัตถุวัฏจักรชีวิตของวัตถุ & การฉีดการพึ่งพาของแอปพลิเคชันวัตถุ

ในแง่นั้น DI นั้นไม่เหมือนกับ Io Cเนื่องจากไม่ได้เกี่ยวกับการควบคุมการไหล แต่เป็น Io *ชนิดเช่น Inversion ของการเป็นเจ้าของการสร้างวัตถุ

เกิดอะไรขึ้นในการอธิบาย DI และ IoC ของฉัน


0

IoC หรือที่รู้จักว่า Inversion of Control หมายถึงการควบคุมการสร้างอินสแตนซ์ที่กระทำโดย Spring container การควบคุมสำหรับการสร้างและการสร้างวัตถุนั้นได้รับการดูแลโดยคอนเทนเนอร์ ภาชนะสร้างวัตถุและฉีดเข้าไปในโปรแกรมของเรา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.