Answer: What are the benefits of Spring IoC? Author: Sevenvidia
7 principles of design patterns
The reason why some people say design patterns are dead is because frameworks like Spring help you manage classes and objects, and let you write code that focuses on what you implement, not design. Let’s start with the seven principles of design patterns:
-
Open – close principle
-
Single responsibility principle
-
Rely on the inversion principle
-
Principle of least knowledge
-
Interface Isolation Principle
-
Synthesis/polymerization reuse principle
-
Richter’s substitution rule says that wherever a base class can appear, a subclass must appear
Dependency inversion
Suppose we design a car: design the wheels first, then design the chassis according to the size of the wheels, then design the body according to the chassis, and finally design the whole car according to the body. Here comes a “dependency” relationship: the car depends on the body, the body depends on the chassis, and the chassis depends on the wheels.
At this time, the boss said to change the design of the wheel, we only need to change the design of the wheel, and do not need to move the chassis, body, car design. This is the dependence inversion principle — the original high-rise building depends on the bottom of the building “inverted” over, become the bottom of the building depends on the high-rise building. The tall building decides what is needed, and the bottom fulfils those needs, but the high building does not manage how the bottom fulfils those needs. This will not appear in front of the “pull a start the whole body” situation.
Inversion of Control
Is a kind of code design idea that relies on inversion principle. The specific method adopted is known as Dependency Injection. In fact, these concepts will feel foggy at first contact. To put it bluntly, the relationship between these concepts is as follows:
To understand these concepts, let’s use the car example above. Only this time in code. Let’s define four classes: car, body, chassis, and tire. And then we initialize the car, and then we run the car. The code structure is as follows:
Thus, as in the first example above, the superstructure depends on the substructure — each class constructor calls the constructor of the underlying code directly. Suppose we need to change the Tire class to have a dynamic size instead of 30 all the time. We need to change it like this:
Since we changed the tire definition, we need to make the following changes in order for the program to work:
As you can see, just to change the tire constructor, this design needs to change the constructors of the entire upper class! In software engineering, such a design would be almost unmaintainable — in a real engineering project, some classes might be at the bottom of thousands of classes, and it would be too expensive to maintain software if every time we changed this class, we had to change all the classes that depend on it. So we need inversion of control (IoC), where the top controls the bottom, not the bottom controls the top. We use Dependency Injection to achieve inversion of control. The so-called dependency injection is to pass the lower class as a parameter to the upper class to realize the “control” of the upper class to the lower class. Here we rewrite the definition of the car class using dependency injection passed by the constructor:
Here, we change the tire size to dynamic. Also, in order to make the whole system run smoothly, we need to make the following modifications:
See yet? Here I only need to modify the tire class, not any of the other upper classes. This is obviously easier code to maintain. Moreover, in practical engineering, this design pattern is also conducive to collaboration and unit testing among different groups. For example, four different groups can develop these four classes respectively, so as long as the interfaces are defined, the four different groups can develop at the same time without being restricted by each other. For unit tests, if we were to write a unit test of Car, we could Mock the Framework class into Car, rather than new the Framework, Bottom, and Tire all over again. Here we do dependency injection by passing in the constructor. There are actually two other methods: Setter pass and interface pass. I won’t talk about it here, but the idea is the same, it’s all about inversion of control.
IoC Container
In fact, in the example above, the code that initializes the car class occurs in the inversion of control container.
Obviously you should have noticed that, with dependency injection, a lot of new writing is inevitable during initialization. Here the IoC container solves this problem. This container automatically initializes your code, so you only need to maintain a Configuration (either XML or a piece of code) instead of having to write a large chunk of initialization code each time you initialize a car. This is the first benefit of introducing an IoC Container. The second benefit of an IoC Container is that we don’t need to know the details when we create the instance. In the example above, we manually create a car instance from the bottom to the top:
IoC Containers can hide specific instance creation details directly.
This is the clearest article I’ve seen about inversion of control, and it’s not about the framework, it’s about the design itself, so starting with the principles of design patterns, let’s move on to some spring practices, and simply building two little wheels.
reading
- [Leetcode] 67. Binary sum
- Design and implementation of on-line diagnosis system
- Summary of technical articles
- [HTTP] Management of distributed sessions