How to use Dependency Injection without breaking encapsulation?

前端 未结 9 594
囚心锁ツ
囚心锁ツ 2020-12-23 09:24

How can i perform dependency injection without breaking encapsulation?

Using a Dependency Injection example from Wikipedia:

public Car {
    public f         


        
相关标签:
9条回答
  • 2020-12-23 10:14

    This is where I think you must use dependency injection containers that let you encapsulate the creation of your car, without letting your client callers need to know how to create it whatsoever. Here's how symfony solved this problem (even though it is not the same language, principles remain the same):

    http://components.symfony-project.org/dependency-injection/documentation

    there is a section on dependency injection containers.

    To make it short and summarize it all quoted from the documentation page directly:

    When using the container, we just ask for a mailer object [This would be your car in your example], and we don't need to know anything about how to create it anymore; all the knowledge about how to create an instance of the mailer [car] is now embedded into the container.

    It the hope that it helps you

    0 讨论(0)
  • 2020-12-23 10:14

    I haven't used Delphi in a long time. The way DI works in Spring, your setters and constructor aren't part of the interface. So you can have multiple implementations of an interface, one might use constructor-based injection and another might use setter-based injection, your code that uses the interface doesn't care. What's injected is in the application-context xml, and that is the only place that your dependencies are exposed.

    EDIT: If you use a framework or not you're doing the same thing, you have a factory that wires together your objects. So your objects expose these details in the constructor or in setters, but your application code (outside of the factory, and not counting tests) never uses them. Either way you choose to get your object graph from the factory rather than instantiate stuff on the fly, and you choose to not do things like use setters in the code that are there to be injected into. It is a mind-shift from the "nail-everything-down" philosophy I see from some people's code.

    0 讨论(0)
  • 2020-12-23 10:20

    I think you're breaking encapsulation with your Car constructor. Specifically you're dictating that an Engine must be injected to the Car instead of some type of interface used to determine your speed (IVelocity in the below example.)

    With an interface, the Car is able to get it's current speed independent of what's determining that speed. For example:

    public Interface IVelocity {
       public float getSpeed();
    }
    
    public class Car {
       private m_velocityObject;
       public constructor(IVelocity velocityObject) { 
           m_velocityObject = velocityObject; 
       }
       public float getSpeed() { return m_velocityObject.getSpeed(); }
    }
    
    public class Engine : IVelocity {
       private float m_rpm;
       private float m_currentGearRatio;
       public float getSpeed( return m_rpm * m_currentGearRatio; );
    }
    
    public class GPS : IVelocity {
        private float m_foo;
        private float m_bar;
        public float getSpeed( return m_foo * m_bar; ); 
    }
    

    An Engine or GPS can then have multiple interfaces based upon the type of work that it does. The interface is key to DI, without it DI does break encapsulation.

    0 讨论(0)
自定义标题
段落格式
字体
字号
代码语言
提交回复
热议问题