Object-Oriented Design Principle 4: Dependency inversion principle

Source: Internet
Author: User

Dependency inversion principle

The Dependence Inversion Principle is dependent on abstraction, not specific. Simply put, it is to program the abstraction and do not program the implementation. This reduces the coupling between the customer and the implementation module.

For process-oriented development, the upper layer calls the lower layer, and the upper layer depends on the lower layer. When the lower layer changes dramatically, the upper layer also changes, this will reduce the reusability of modules and greatly increase the development cost.

Object-Oriented development solves this problem very well. In general, the probability of abstract changes is very small, so that user programs depend on abstraction, and the Implementation Details depend on abstraction. Even if the implementation details are constantly changing, the customer program will not need to change as long as the abstraction remains unchanged. This greatly reduces the coupling between the implementation details of the customer's program domain.

For example, a joint venture automobile company now requires the development of an autonomous system. As long as the car is installed with this system, self-driving can be realized. This system can be used in the Ford and Honda series. Process-oriented structure:

The implementation code is as follows:

Public class HondaCar

{

Public void Run () {Console. WriteLine ("Honda started! ");}

Public void Turn () {Console. WriteLine ("Honda turned! ");}

Public void Stop () {Console. WriteLine ("Honda car stopped! ");}

}

Public class FordCar

{

Public void Run () {Console. WriteLine ("Ford started! ");}

Public void Turn () {Console. WriteLine ("Ford turned! ");}

Public void Stop () {Console. WriteLine ("Ford stops! ");}

}

Public class AutoSystem

{

Public enum CarType {Ford, Fonda}

Private HondaCar hondcar = new HondaCar ();

Private FordCar fordcar = new FordCar ();

Private CarType type;

Public AutoSystem (CarType carType)

{

This. type = carType;

}

Public void RunCar ()

{

If (this. type = CarType. Fonda)

{

Hondcar. Run ();

}

Else if (this. type = CarType. Ford)

{

Fordcar. Run ();

}

}

Public void StopCar ()

{

If (this. type = CarType. Fonda)

{

Hondcar. Stop ();

}

Else if (this. type = CarType. Ford)

{

Fordcar. Stop ();

}

}

Public void TurnCar ()

{

If (this. type = CarType. Fonda)

{

Hondcar. Turn ();

}

Else if (this. type = CarType. Ford)

{

Fordcar. Turn ();

}

}

}

Obviously, this implementation code can also meet the current needs.

But how can the company's business scale expand now, the self-driving system should also be compatible with jeeps. You need to modify the AutoSystem class as follows:

Public class AutoSystem

{

Public enum CarType {Ford, Fonda, Jeep}

Private HondaCar hondcar = new HondaCar ();

Private FordCar fordcar = new FordCar ();

Private Jeep jeep = new Jeep ();

Private CarType type;

Public AutoSystem (CarType carType)

{

This. type = carType;

}

Public void RunCar ()

{

If (this. type = CarType. Fonda)

{

Hondcar. Run ();

}

Else if (this. type = CarType. Ford)

{

Fordcar. Run ();

}

Else if (this. type = CarType. Jeep)

{

Jeep. Run ();

}

}

Public void StopCar ()

{

If (this. type = CarType. Fonda)

{

Hondcar. Stop ();

}

Else if (this. type = CarType. Ford)

{

Fordcar. Stop ();

}

Else if (this. type = CarType. Jeep)

{

Jeep. Stop ();

}

}

Public void TurnCar ()

{

If (this. type = CarType. Fonda)

{

Hondcar. Turn ();

}

Else if (this. type = CarType. Ford)

{

Fordcar. Turn ();

}

Else if (this. type = CarType. Jeep)

{

Jeep. Turn ();

}

}

}

The code analysis shows that the above Code meets the requirements, but the software is constantly changing, and the demand for software is also changing. If the business expands in the future, the self-driving system can also implement general purpose, Mitsubishi, and Volkswagen, so we have to modify the AutoSystem class again. This will cause the system to become more and more bloated and larger, and rely on more and more lower-layer modules. Only the lower-layer modules change, the AutoSystem class has to be changed, resulting in the system design become very fragile and stiff.

One cause of the problem described above is that modules with high-level policies, such as the AutoSystem module, depend on the specific details of the lower layers it controls (such as FordCar and HondaCar ). If the AutoSystem module is independent of the specific details it controls, but dependent on abstraction, then we can take it. This is the "Dependency inversion" mechanism in object-oriented systems. The following class diagram:

 

The implementation code is as follows:

Public interface ICar

{

Void Run ();

Void Stop ();

Void Turn ();

}

Public class HondaCar: ICar

{

Public void Run () {Console. WriteLine ("Honda started! ");}

Public void Turn () {Console. WriteLine ("Honda turned! ");}

Public void Stop () {Console. WriteLine ("Honda car stopped! ");}

}

Public class FordCar: ICar

{

Public void Run () {Console. WriteLine ("Ford started! ");}

Public void Turn () {Console. WriteLine ("Ford turned! ");}

Public void Stop () {Console. WriteLine ("Ford stops! ");}

}

Public class Jeep: ICar

{

Public void Run () {Console. WriteLine ("Ford started! ");}

Public void Turn () {Console. WriteLine ("Ford turned! ");}

Public void Stop () {Console. WriteLine ("Ford stops! ");}

}

Public class AutoSystem

{

Private ICar car;

Public AutoSystem (ICar car)

{

This. car = car;

}

Public void RunCar ()

{

This. car. Run ();

}

Public void StopCar ()

{

This. car. Stop ();

}

Public void TurnCar ()

{

This. car. Turn ();

}

}

Currently, the Autosystem system depends on the ICar abstraction, but it has nothing to do with the specific implementation details HondaCar: And FordCar. Therefore, changes in implementation details will not affect AutoSystem. You only need to implement ICar for implementation details. That is, the Implementation Details depend on ICar abstraction.

To sum up, an important policy decision and business in an application are in these high-level modules. These modules also contain the characteristics of this application. However, when these modules depend on the lower-layer modules, modifications to the lower-layer modules will directly affect them and force them to change. This is ridiculous.

It should be a high-level module that forces those lower-level modules to change. Higher-level modules should take precedence over lower-level modules. In any case, the upper-level module should not depend on the lower-level module. What we want to reuse is a high-level module. Only when the High-Level module is independent from the low-level module can it be reused.

In short, high-level modules should not depend on low-level modules. They should all depend on abstraction. Abstraction should not depend on specifics, but on abstraction.

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.