Interpretation of Microsoft objectbuilder: constructing a lightweight dependency injection container (1) Dependency inversion

Source: Internet
Author: User

Dependency injection or inverse of control (control reversal) design patterns come from a basic principle of Architecture Design:

1. Dependency inverse Policy (dependency inversion/dependency inversion)
What is dependency inversion/dependency inversion? Let's look at a simple example: a console Program Read the string input by the user from the keyboard and output it to the screen.
Static void main (string [] ARGs)
{
Console. writeline ("demo dip ");
String S = console. Readline ();
Console. writeline ("your input is" + S );
Console. Read ();
}, Ah, Code The logical coupling is too tight. Let's split it up a little bit and use some procedural design in C. Change it:
Class Program
{
Static void main (string [] ARGs)
{
Console. writeline ("demo dip ");
String S = messagecreater ();
Messageprocessor (s );
Console. Read ();
}
Static string messagecreater ()
{
Return console. Readline ();
}
Static void messageprocessor (string S)
{
Console. writeline ("your input is" + S );
}
}
With object-oriented, we can use objects to encapsulate the following two functions.
Class Program
{
Static void main (string [] ARGs)
{
Console. writeline ("demo dip ");
String S = new consolemessagecreator (). Create ();
New lelemessageprocessor (). Process (s );
Console. Read ();
}

}

public class consolemessagecreator
{< br> Public string create ()
{< br> return console. readline ();
}< BR >}< br> public class consolemessageprocessor
{< br> Public void process (string S)
{< br> console. writeline ("your input is" + S);
}< BR >}

Everything looks good. The Code logic is encapsulated in their respective classes. If the user needs remain unchanged, there is no problem. But one day the customer said that if the message is order, it will be output to the printer; otherwise, it will go to the screen. The Code should be changed:
Public class printermessageprocessor (added)
{
Public void process (string S)
{
Printer. Print (s );
}
}
...
Static void main (string [] ARGs)
{
Console. writeline ("demo dip ");
String S = new consolemessagecreator (). Create ();
If (S = "order ")
{
New printermessageprocessor (). Process (s );
}
Else
{
New lelemessageprocessor (). Process (s );
}
Console. Read ();
}

The problem starts. The code in main will be changed all the time. if then else or switch is required for a new message processor ....
Where is the root cause of the problem? Let's take a look at the group relationship diagram.


The upper-layer object main depends on the specific implementation of the underlying object printermessageprocessor, consolemessageprocessor, and consolemessagecreator. As a result, the upper-layer objects are constantly changing to cope with the underlying changes. This is what we call the subject dependency details, the upper layer logic depends on the underlying implementation. As a result, the upper main component remains in the modification and is difficult to stabilize (another definition of stability in OO can be understood as reuse .) This design is difficult to solve the problem of changing requirements. (Here is a change in the message processing mechanism)
So how should we solve the above problems? This involves other architectural design principles.

1) interface/abstract Programming

2) extract changes for encapsulation and isolate changes. (Changes will spread, so we need to encapsulate the changes. The main purpose of the architecture design is to differentiate the stable (or relatively stable) parts and the changed parts-effecect for change)

What is an interface:

The interface is the external contract of the component. The understanding of the component is to look at its interface. The interface describes what the component can do. Therefore, the interface should be stable or relatively stable (relative to the internal logic ), if the interface of a component changes frequently, the component design may be faulty.
Abstract is similar to an interface (abstract class and interface are different later, or you can Google it). It abstracts specific functions to maintain external stability.
We also mentioned the encapsulation change point, which isolates the change point to maintain the external stability of the component. So how can we modify our example by using these two architectural design principles?

From the lelemessageprocessor and printermessageprocessor code, we can see that they all have only one common method, and the main calls to them only involve this common method. This is the interface we are looking.

Public interface imessageprocessor
{
Void process (string message );
}

By the way, the component generated by the message is also interface-based. (The extreme practice of design is that only interface calls are allowed between components .)
Public interface imessagecreator
{
String create ();
}

The next question is how to implement interface-specific programming? In fact, it is very simple to make the relationship between the main component and the underlying Component Interface/or abstract. The underlying component only exposes the interface to the main component, and the main interrupt calls the specific type of the underlying component, in this way, the coupling relationship between the main component and the underlying component is changed to the coupling relationship between the main component and the interface, and the interface is relatively stable, so our goal is achieved. Let's take a look at the modified component relationship diagram.

 

2. Interface/abstract-based programming

In simple terms, dependency is that a component and an object have a direct call relationship with another component or object. Now let's look at the component diagram. Main depends on the interface components, and the underlying message processing and generation components also depend on the interface components (the main dependency on the underlying specific components is reversed ). the advantage of this is that the Code in the main is stable, and the new message processing component does not need to be changed (or rarely changed) The main code.

In the subsequent series, we will studySource codeWe will find that it follows this principle well.

 
For the above example, our specific code is changed:
Public interface imessageprocessor
{
Void process (string message );
}

Public interface imessagecreator
{
String create ();
}

Public class lelemessageprocessor: imessageprocessor
{
Public void process (string message)
{
Console. writeline (Message + "processed by lelemessageprocessor .");
}
}

Public class printermessageprocessor: imessageprocessor
{
Public void process (string message)
{
Printer. Print (Message );
}
}

Public class lelemessagecreator: imessagecreator
{
Public string create ()
{
Return console. Readline ();
}
}

The modified main code is as follows:
Static void main (string [] ARGs)
{
Console. writeline ("demo dip ");
Imessagecreator messagecreator = NULL;
Imessageprocessor messageprocessor = NULL;
// Messagecreator =...
// Messageprocessor = ..
String S = messagecreator. Create ();
Messageprocessor. Process (s );
Console. Read ();
}
Ah, the problem comes again. There is still an important step to stabilize the main code. messagecreator and messageprocessor are not instantiated. Who will give me this instance? Hope god can help me with this. Simply change the code:
Static void main (string [] ARGs)
{
Console. writeline ("demo dip ");
Imessagecreator messagecreator = NULL;
Imessageprocessor messageprocessor = NULL;
Messagecreator = god. messagecreator;
Messageprocessor = god. messageprocessor;
String S = messagecreator. Create ();
Messageprocessor. Process (s );
Console. Read ();
}
Now the change point of the main code has been transferred to the god object, which is in line with what we just mentioned:

With changes, isolate and encapsulate it.

All we have to do is implement our own god object, so the factory mode was unveiled!

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.