In the context of the class relationship, we talked about the relationship between the classes and the class, and here we delve into the communication between the object and the object. Why do you want to go into the communication between objects and objects, it is basically that there is no unique object in the system, the different objects are bound to communicate with each other.
A beginner's question
Before we begin to introduce the Dimitri Law, let us go to the age of beginner programming.
When we first learned to program, we usually declared all the methods as public, but as our code volume increased, we encountered a typical problem:
When invoking the method of an object, we find that the compiler hints at all methods of the object, which means that the object is in an unsafe state. Why do you say that? If we compare this object to a person, then this person is naked in front of others, without any privacy, which gives others the opportunity to observe all of your actions, and a deadly blow. In addition, this completely exposed person, also can let others at a loss.
This is obviously not what we want, so we need some kind of mechanism to restrict the disclosure of object information: What information is public and which is not, in Java, we do this through the permissions of the method, such as the private adornment method only the object can be called internally, The public adornment method is exposed to other objects, and so on.
Now, you may already understand why Java designers are "superfluous" to design permissions for the method. Then someone would ask, how can I be sure which method should be designed to be public and which should be designed as private?
When you have this question in mind, you are beginning to focus on one of the principles of object-oriented programming that we often refer to: encapsulation, that is, how to divide the structure of an object.
We all know that the structure of an object can be divided into static properties and dynamic properties, so-called static properties are intrinsic properties of value objects, such as any life body has age, and dynamic properties are also known as behavioral properties, refers to the behavior of the object, such as the kangaroo can jump, can breathe and so on. The static and dynamic properties can be subdivided into public static properties, public dynamic properties, and so on. In other words, the structure of the object is to determine the dynamic and static properties of an object, on this basis to determine whether the property can be exposed and so on.
It is not difficult to see that this process is similar to our cognitive thinking process: The brain tries to extract features from a variety of objects. For example, we see cats, dogs, cacti, in order to distinguish them, our brains will be on these three feature extraction, such as cats and dogs can move, have eyes, will bark, have claws, and cactus is not movable, there are thorns, can not be called, through this special extraction, we can distinguish between animal and plant differences. In other words, we can distinguish different objects, because our brains have been silently for us to do feature extraction work, this process if we take the initiative to do is called abstract programming.
Secret Dimitri Law
The Dimitri rule (law of Demeter, abbreviated as LOD) requires that one object should have a minimum of knowledge of other objects, and deflation is that a class knows as little as possible of the classes it relies on, that is, for the classes that are dependent, the methods that are exposed to it should be as few.
There is another explanation for the Dimitri law: only talk toyour immediate friends, which communicates only with direct friends.
The first is to explain the friends in programming: the coupling relationship between two objects is called a friend, usually with dependencies, associations, aggregations, and compositions. While direct friends are usually represented as associations, aggregations, and constituent relationships, two objects are more closely connected, usually in the form of member variables, method parameters, and return values.
So why would you want to communicate with a direct friend? Observing where direct friends appear, we find that in most cases the presence of a direct friend can be replaced by an interface or a parent, which increases flexibility.
(It is important to note that when considering this issue, we only consider new classes and ignore the underlying classes that Java provides for us.)
It is easy to see that the Dimitri rule emphasizes two points:
- The first thing: from the point of view of the dependent: exposing only methods or properties that should be exposed, that is, determining the permissions of a method/attribute when writing related classes
- The second important point: from the perspective of the relying person, only depends on the object that should depend on
Example Demo
First to explain the 1th, we use the computer to illustrate, Consider the process of shutting down the computer. When we press the computer's Shutdown button, the computer performs some column actions that are performed: such as saving the current unfinished task, then shutting down the related service, then shutting down the monitor, and finally turning off the power, the computer will be officially shut down after this sequence of operations is completed.
Let's use simple code to represent this process, without considering the Dimitri rule, we might write the following code
//Computer class Public classcomputer{ Public void Savecurrenttask(){//do something} Public void Closeservice(){//do something} Public void Closescreen(){//do something} Public void Closepower(){//do something} Public void Close() {savecurrenttask (); Closeservice (); Closescreen (); Closepower (); }} Public classperson{PrivateComputer C; ... Public void Clickclosebutton(){///Now you have to start shutting down the computer, normally you just need to call the close () method, //But you find computer all the methods are public, how to close it? So you wrote down the following closing process:C.savecurrenttask (); C.closepower (); C.close ();//or the following actions:C.closepower ();//may also be the following actionsC.close (); C.closepower (); }}
Did you find the problem in the code above? Observing the Clickclosebutton () method, we found that this method could not be written: C is a completely exposed object, the method is completely public, then for person, when he wants to perform close, but found that do not know how to do: What method should I call? guess what? If the person's object is a non-computer, then the object of this is not to be ruined?
The first gist of Dimitri Law
Now let's take a look at the 1th of the Dimitri Law: from the point of view of the dependent, only the methods that should be exposed should be exposed. So what should be the methods of the C object here should be exposed? Obviously, for person, you only need to focus on the shutdown of the computer, not how the computer will handle the shutdown, so you only need to expose the close() method.
Then the above code should be modified to:
//Computer class Public classcomputer{Private void Savecurrenttask(){//do something}Private void Closeservice(){//do something}Private void Closescreen(){//do something}Private void Closepower(){//do something} Public void Close() {savecurrenttask (); Closeservice (); Closescreen (); Closepower (); }} Public classperson{PrivateComputer C; ... Public void Clickclosebutton() {c.close (); }}
Take a look at its class diagram:
Next, we continue to look at the second meaning of the Dimitri Law: from the point of view of the relying person, only the object that should depend on.
This sentence is a bit confusing, what is called should depend on the object?
Or use the "Turn off the computer" example above to illustrate:
Technically, the computer includes the operating system and related hardware, which we can classify as system objects and container objects. When we shut down the computer, we essentially issued a shutdown command to the operating system, but in fact we just pressed the shutdown button, that is, we do not rely on the system object, but rely on the container. Here container is what we call a direct friend-just communicate with a direct friend.
Let's discuss this in more detail:
only talk to your immedate friends
This sentence only means to communicate with a direct friend, but I think this is not complete, I would like to add it as:
make sure your friends,only talk to your immedate friends,don‘t speak to strangers.
determine your true friends and only communicate with them, and don't talk to strangers. A great benefit of this is the ability to simplify communication between objects and objects, thereby reducing dependencies, providing greater flexibility and, of course, providing a certain level of security.
Now think of a situation in the real world: You are an eye-catching public figure, everyone around you knows your name, what kind of scene will it be when you walk alone on the street? Everyone wants to chat with you!, and you exchange information!! Then you find yourself in a difficult situation. If you have a broker at this time to help you deal with the people around you, and you only communicate with this agent, it will greatly reduce your pressure, right? At this point, the economic person is the equivalent of your direct friend.
The second essence of Dimitri Law
Now, as we look back on the "Shut down computer" operation, the previous code just follows the first one, and now we're going to improve with the second: system is not a direct friend of the person compared to container, and container is ( The person directly deals with container). So we need to split the original computer into system and Cotainer, and then make the person only communicate with container, so the code is modified to:
//system Public classsystem{Private void Savecurrenttask(){//do something}Private void Closeservice(){//do something}Private void Closescreen(){//do something}Private void Closepower(){//do something} Public void Close() {savecurrenttask (); Closeservice (); Closescreen (); Closepower (); }}//contanier Public classcontainer{PrivateSystem Msystem; Public void Sendclosecommand() {msystem.close (); }}//personUblic class person{PrivateContainer C; .... Public void Clickclosebutton() {C.sendclosecommand (); }}
Take a look at its class diagram:
The second essence of the extension
In the above, we also mentioned that where direct friends appear, we can use their interfaces or parent classes instead. So here we can provide the appropriate interface for container and system
//system Interface Public interface ISystem{ voidClose ();}//system Public class System implements ISystem{ Private void Savecurrenttask(){//do something}Private void Closeservice(){//do something}Private void Closescreen(){//do something}Private void Closepower(){//do something}@override Public void Close() {savecurrenttask (); Closeservice (); Closescreen (); Closepower (); }}//icontainer Interface Public interface icontainer{ voidSendclosecommand ();}//contanier Public class Container implements IContainer{ PrivateSystem Msystem;@override Public void Sendclosecommand() {msystem.close (); }}//personUblic class person{PrivateIContainer C; .... Public void Clickclosebutton() {C.sendclosecommand (); }}
Take a look at its class diagram:
Comparing these two schemes, it is obvious that the decoupling degree of this scheme is higher and the flexibility is greatly enhanced. It is not difficult to see that this applies the dependency inversion we mentioned earlier, i.e. interface-oriented programming.
Beyond that, we find that as the number of classes continues to evolve, from 2 to 5, it means that the number of classes that are typically written to understand decoupling and increase flexibility doubles. So you need to do a trade-off in this, not deliberately in order to pursue the design, resulting in the entire system is very redundant, The end result may outweigh the gains.
Summarize
Some people think that container is like an intermediary (agent). Yes, we can actually call it an intermediary, but it doesn't deny that he is our direct friend: In many cases, intermediaries can be said to be one of our representatives, so it is no problem to define them as direct friends. For example, When you want to rent, you can find a housing agency, the other side will follow your criteria for you to find the right housing.
But here's the question: How many intermediaries do you need to do one thing? Can't be I commissioned an intermediary a help me find a house, but intermediary a and commissioned intermediary B, intermediary B and entrusted the intermediary C .... And so on, if that's the case, it's better for me to find the house myself. In actual development, The level of the delegation to be controlled below 6 layer, more than 6 layers will make the system excessively redundant and and will be too much to the level of delegation, which leads to the developers can not correctly understand the process, the risk can be greatly improved.
Vernacular design--in-depth understanding of LOD