The following text is from Java to javaee.
During module design, a high-level abstract module is usually a business-related module. It should be reusable and independent from a lower-layer module. For example, if a lower-level module is originally a disk access mode, the high-level module is an archive backup requirement. If the High-Level module directly calls the method of the lower-level module, the dependency between the lower-level module is generated.
For example, the following code:
//...void save(){ //... saveToFloppy();}
Because the SAVE () method depends on savetofloppy (), if you want to change the Low-layer storage mode to USB, this method cannot be reused and must be modified, the changes to the lower-layer mode make the upper-layer mode also have to be changed. This is not a good design method. In design, we hope that the mode will depend on the abstraction of the mode, in this way, the upper-layer business design can be reused. If it is designed in an object-oriented way, the dependecy inversion interpretation should not depend on implementation, but on abstraction. Implementation must depend on abstraction. Let's take a look at the following Java method:
public class BusinessObject{ private FloppyWriter writer=new FloppyWriter();//... public void save(){ //... writer.saveToFloppy(); }}
In this method, the archiving of businessobject depends on the actual floppywriter. To save it to USB, you must modify or inherit businessobject, instead of using businessobject directly.
If the structure is used, this situation can be improved, for example:
public interface IDeviceWriter{ public void saveToDevice();}public void BusinessObject{ private IDeviceWriter writer; public void setDeviceWriter(IDeviceWriter writer){ this.writer=writer; } public void save(){ writer.saveToDevice(); }}
In this way, businessobject can be reused. If you need to store it to floppy or USB, you only need to inherit idevicewriter without modifying businessobject:
Public class floppywriter implement idevicewriter {public void savetodevice () {// Method for storing actually to Floppy} public class usbdiskwriter implement idevicewriter {public void savetodevice () {// Method for storing data to USB }}
From this perspective, dependency inversion means that a method does not depend on implementation, but both methods and implementations depend on abstraction.
IOC control is the meaning of control, and the meaning behind it is also the transfer of dependency. If a depends on B, it means that B has control and wants to transfer this relationship, therefore, the inversion of dependency is the reversal of control relationships, which are transferred from control relationships. Component reusability can be obtained. In the preceding Java method, the entire control is transferred from the actual floppywriter to the abstract idevicewriter interface. This makes businessobject, floppywriter, and usbdiskwriter dependent on the abstract idevicewriter interface.
The business logic part of the method should be reusable and should not be affected by the framework or container used, because the entire business logic may be transferred to other frameworks or containers, if the business logic is too dependent on the container, it is difficult to transfer it to another framework or container.
From the container perspective, IOC can describe in one sentence-"Don't call me, I'll call you", that is, "do not request the required (object) resources from the container, the container will automatically send these objects to you! ". IOC requires the container not to intrude into the method itself, and the method itself provides a good interface, the container can inject the required resources into the method through these interfaces, the method does not actively request resources from the container, therefore, it does not depend on the container components. The method itself does not realize that it is being used by the container. It can be removed from the container at any time without any modification, this feature is most required by some business logic middleware.