What is Inversion of Control?

前端 未结 30 2675
清歌不尽
清歌不尽 2020-11-22 00:13

Inversion of Control (IoC) can be quite confusing when it is first encountered.

  1. What is it?
  2. Which problem does it solve?
  3. When is it appropria
相关标签:
30条回答
  • 2020-11-22 00:37

    Let to say that we make some meeting in some hotel.

    Many people, many carafes of water, many plastic cups.

    When somebody want to drink, she fill cup, drink and throw cup on the floor.

    After hour or something we have a floor covered of plastic cups and water.

    Let invert control.

    The same meeting in the same place, but instead of plastic cups we have a waiter with one glass cup (Singleton)

    and she all of time offers to guests drinking.

    When somebody want to drink, she get from waiter glass, drink and return it back to waiter.

    Leaving aside the question of the hygienic, last form of drinking process control is much more effective and economic.

    And this is exactly what the Spring (another IoC container, for example: Guice) does. Instead of let to application create what it need using new keyword (taking plastic cup), Spring IoC container all of time offer to application the same instance (singleton) of needed object(glass of water).

    Think about yourself as organizer of such meeting. You need the way to message to hotel administration that

    meeting members will need glass of water but not piece of cake.

    Example:-

    public class MeetingMember {
    
        private GlassOfWater glassOfWater;
    
        ...
    
        public void setGlassOfWater(GlassOfWater glassOfWater){
            this.glassOfWater = glassOfWater;
        }
        //your glassOfWater object initialized and ready to use...
        //spring IoC  called setGlassOfWater method itself in order to
        //offer to meetingMember glassOfWater instance
    
    }
    

    Useful links:-

    • http://adfjsf.blogspot.in/2008/05/inversion-of-control.html
    • http://martinfowler.com/articles/injection.html
    • http://www.shawn-barrett.com/blog/post/Tip-of-the-day-e28093-Inversion-Of-Control.aspx
    0 讨论(0)
  • 2020-11-22 00:38

    Answering only the first part. What is it?

    Inversion of Control (IoC) means to create instances of dependencies first and latter instance of a class (optionally injecting them through constructor), instead of creating an instance of the class first and then the class instance creating instances of dependencies. Thus, inversion of control inverts the flow of control of the program. Instead of the callee controlling the flow of control (while creating dependencies), the caller controls the flow of control of the program.

    0 讨论(0)
  • 2020-11-22 00:38

    I found a very clear example here which explains how the 'control is inverted'.

    Classic code (without Dependency injection)

    Here is how a code not using DI will roughly work:

    • Application needs Foo (e.g. a controller), so:
    • Application creates Foo
    • Application calls Foo
      • Foo needs Bar (e.g. a service), so:
      • Foo creates Bar
      • Foo calls Bar
        • Bar needs Bim (a service, a repository, …), so:
        • Bar creates Bim
        • Bar does something

    Using dependency injection

    Here is how a code using DI will roughly work:

    • Application needs Foo, which needs Bar, which needs Bim, so:
    • Application creates Bim
    • Application creates Bar and gives it Bim
    • Application creates Foo and gives it Bar
    • Application calls Foo
      • Foo calls Bar
        • Bar does something

    The control of the dependencies is inverted from one being called to the one calling.

    What problems does it solve?

    Dependency injection makes it easy to swap with the different implementation of the injected classes. While unit testing you can inject a dummy implementation, which makes the testing a lot easier.

    Ex: Suppose your application stores the user uploaded file in the Google Drive, with DI your controller code may look like this:

    class SomeController
    {
        private $storage;
    
        function __construct(StorageServiceInterface $storage)
        {
            $this->storage = $storage;
        }
    
        public function myFunction () 
        {
            return $this->storage->getFile($fileName);
        }
    }
    
    class GoogleDriveService implements StorageServiceInterface
    {
        public function authenticate($user) {}
        public function putFile($file) {}
        public function getFile($file) {}
    }
    

    When your requirements change say, instead of GoogleDrive you are asked to use the Dropbox. You only need to write a dropbox implementation for the StorageServiceInterface. You don't have make any changes in the controller as long as Dropbox implementation adheres to the StorageServiceInterface.

    While testing you can create the mock for the StorageServiceInterface with the dummy implementation where all the methods return null(or any predefined value as per your testing requirement).

    Instead if you had the controller class to construct the storage object with the new keyword like this:

    class SomeController
    {
        private $storage;
    
        function __construct()
        {
            $this->storage = new GoogleDriveService();
        }
    
        public function myFunction () 
        {
            return $this->storage->getFile($fileName);
        }
    }
    

    When you want to change with the Dropbox implementation you have to replace all the lines where new GoogleDriveService object is constructed and use the DropboxService. Besides when testing the SomeController class the constructor always expects the GoogleDriveService class and the actual methods of this class are triggered.

    When is it appropriate and when not? In my opinion you use DI when you think there are (or there can be) alternative implementations of a class.

    0 讨论(0)
  • 2020-11-22 00:38

    I've read a lot of answers for this but if someone is still confused and needs a plus ultra "laymans term" to explain IoC here is my take:

    Imagine a parent and child talking to each other.

    Without IoC:

    *Parent: You can only speak when I ask you questions and you can only act when I give you permission.

    Parent: This means, you can't ask me if you can eat, play, go to the bathroom or even sleep if I don't ask you.

    Parent: Do you want to eat?

    Child: No.

    Parent: Okay, I'll be back. Wait for me.

    Child: (Wants to play but since there's no question from the parent, the child can't do anything).

    After 1 hour...

    Parent: I'm back. Do you want to play?

    Child: Yes.

    Parent: Permission granted.

    Child: (finally is able to play).

    This simple scenario explains the control is centered to the parent. The child's freedom is restricted and highly depends on the parent's question. The child can ONLY speak when asked to speak, and can ONLY act when granted permission.

    With IoC:

    The child has now the ability to ask questions and the parent can respond with answers and permissions. Simply means the control is inverted! The child is now free to ask questions anytime and though there is still dependency with the parent regarding permissions, he is not dependent in the means of speaking/asking questions.

    In a technological way of explaining, this is very similar to console/shell/cmd vs GUI interaction. (Which is answer of Mark Harrison above no.2 top answer). In console, you are dependent on the what is being asked/displayed to you and you can't jump to other menus and features without answering it's question first; following a strict sequential flow. (programmatically this is like a method/function loop). However with GUI, the menus and features are laid out and the user can select whatever it needs thus having more control and being less restricted. (programmatically, menus have callback when selected and an action takes place).

    0 讨论(0)
  • 2020-11-22 00:39

    But I think you have to be very careful with it. If you will overuse this pattern, you will make very complicated design and even more complicated code.

    Like in this example with TextEditor: if you have only one SpellChecker maybe it is not really necessary to use IoC ? Unless you need to write unit tests or something ...

    Anyway: be reasonable. Design pattern are good practices but not Bible to be preached. Do not stick it everywhere.

    0 讨论(0)
  • 2020-11-22 00:39

    Inversion of control is about transferring control from library to the client. It makes more sense when we talk about a client that injects (passes) a function value (lambda expression) into a higher order function (library function) that controls (changes) the behavior of the library function. A client or framework that injects library dependencies (which carry behavior) into libraries may also be considered IoC

    0 讨论(0)
提交回复
热议问题