"I want to use the golden finger" -- From the Perspective of the mode to the basic principles of object-oriented Dependency inversion

Source: Internet
Author: User

It is said that one day, God saw a beggar and moved his mercy. He said to the beggar, "I will satisfy your desire. I will give you what you want. To put it bluntly, I am afraid that the Beggars do not believe it. With my hands, a steamed bread appears in front of the beggars. Then, a pile of money appears in front of the beggars. Then, a group of bricks appears in front of the beggars. Of course, the beggars are stunned, and the gods put those back and said to the beggars, say, what do you want? I want your finger.

You can see, how can this smart beggar use the basic object-oriented principle! He knows, whether it's anything, steamed bread, money or gold. Its quantity is limited and there will be an end. If it is spent, there will be no more; but the golden finger is different, although it only has one, however, various specific things can be generated infinitely. If we compare all kinds of specific things, such as steamed buns, money, and gold, and compare beggars, such as users of this class, or dependent objects, the golden finger of God is the abstraction of specific objects. This story tells the story of an object-oriented basic principle-Dependency inversion principle. Its significance lies in the fact that the class users or dependent persons (beggars) cannot depend on a specific class (steamed bread, money, or gold ), it depends on their abstraction (Golden finger ).

Dependency inversion principle: High-level modules should not depend on low-level modules, both of which should depend on abstraction; abstraction should not depend on details, and details should depend on abstraction.

Obviously, there are three main advantages of following this principle: first, good scalability. You can add a specific class that implements the abstract class at any time, users or dependent persons of the class do not need to make any changes. Second, the flexibility for the use of dependent classes is greatly increased. The client can decide which specific class to use at runtime. Third, the code is highly reusable, and all specific classes have a unified interface, so the client does not have to write similar code for each specific class.

The composite (combination) mode is a common mode. It is a mode applied to the structure of the "whole part. As we will talk about, the "Tree" is very suitable for this model, because the relationship between the leaf and the tree is a typical "part and the whole. Next let's take a look at how this mode solves this problem.

First, define an interface:

Public interface treecomponent {
Public void first ();
Public void middle ();
Public void rear ();
Public int deepth ();
}
Then there is the leaf implementation:

Public class leaf implements treecomponent {
Private string leaf;
Public leaf (string leaf)
{
This. Leaf = leaf;
}
Public void first (){
System. Out. println (leaf );
}
Public void middle (){
System. Out. println (leaf );
}
Public void rear (){
System. Out. println (leaf );
}
Public int deepth ()
{
Return 1;
}
}
Tree implementation:

Public class tree implements treecomponent {
Private string treetop;
Private treecomponent left;
Private treecomponent right;
Public tree (string treetop, treecomponent left, treecomponent right)
{
This. treetop = treetop;
This. Left = left;
This. Right = right;
}
Public void first (){
System. Out. println (this. treetop );
If (this. Left! = NULL)
{
This. Left. First ();
}
If (this. Right! = NULL)
{
This. Right. First ();
}

}
Public void middle (){
If (this. Left! = NULL)
{
This. Left. Middle ();
}
System. Out. println (this. treetop );
If (this. Right! = NULL)
{
This. Right. Middle ();
}

}
Public void rear (){
If (this. Left! = NULL)
{
This. Left. Rear ();
}
If (this. Right! = NULL)
{
This. Right. Rear ();
}
System. Out. println (this. treetop );

}

Public int deepth ()
{
Int LD = 0;
Int RD = 0;
If (this. Left! = NULL)
{
LD = This. Left. deepth ();
}
If (this. Right! = NULL)
{
RD = This. Right. deepth ();
}
Return (LD> RD? Ld: RD) + 1;
}
}
We can see that the two dependencies of the tree class are both the treecomponent interface. The lower layers that meet the Dependency inversion principle should rely on the high-level and detailed requirements to rely on abstract requirements. The advantage of doing so is obvious: the tree's left son and right son can both be leaves or trees, so the tree's scalability has been greatly improved; in addition, when using the client, the same algorithm can be used by the tree and leaf, reducing code duplication.

The command mode, policy mode, and status mode have the same idea: Separate the concerns so that they all implement a unified interface and then call the client. There are many advantages: first, the focus is separated to satisfy the single accusation principle, and then the client's dependency on details is transferred to the abstract dependency, in this way, the system has good scalability and can be used during the runtime. The following uses the command mode to see how it complies with the Dependency inversion principle:

Suppose we have the following code:

If (....)
{
// Do action 1
......
}
Else if (...)
{
// Do action 2
......
}
Else if (......)
{
// Do action 3
......
}
......
Obviously, the client has a strong dependence on details. Such code has many disadvantages: first, it is easy to cause logic confusion, so many if... Else ..., Every action may have complicated logic, which can easily cause confusion. The second is not dynamic binding. You need to determine the actions in advance. And so on.

We will transform the code in command mode.

First, create a command interface:

Public interface common
{
Public void docommon ();
}
Then use the code of those actions to implement this interface:

Public class common1 implements common
{
Public void docommon ()
{
// Do action 1
......

 

}
}
Other classes are similar to this, and then we create a factory to produce these specific classes:

Public class factory
{
// Path of these classes
Private string Path = "…";
// Specific production class
Public static common getinstance (string type)
{
Try
{
Class CLS = Class. forname (this. Path + type );
Return (common) CLS. newinstance ()
}
Catch (exception E)
{
Return NULL;
}
}
}
Finally, our client call can look like this:

Common common = factory. getinstance (type );
Common. docommon ();
In this way, the client dependency is converted from the dependency on details to the dependency on Abstract Common, satisfying the principle of dependency inversion. The author of a class (common interface and some specific implementation classes) may not know the specific implementation class that the client needs to call at runtime. It may not be in the specific implementation classes he has made, the implementation class added by the user. As the demand changes, users may need to add new behaviors or actions. It doesn't matter. Users only need to implement the common interface.

It can be said that the principle of dependency inversion is an object-oriented foundation. This principle guides us to use class polymorphism, and then we get the ability to bind at runtime. This capability is one of our most valuable object-oriented technologies. Based on this, the vast majority of models need to use abstraction to transfer dependencies to achieve the purpose of optimizing the design.

In our object-oriented analysis and design process, we are constantly reducing and transferring dependencies, this method of reducing and transferring dependencies is implemented under the guidance of the principle of dependency inversion.

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.