1. Basic introduction
Dependence Inversion Principle refers to:
- A high-level module should not depend on a low-level module; both should depend on its abstraction
2) Abstraction should not depend on details, details should depend on abstractions
-
The central idea of dependency inversion is interface oriented programming
-
The dependency inversion principle is based on the design idea that abstract things are more stable than details. An architecture based on abstraction is much more stable than one based on detail. In Java, abstraction refers to an interface or abstract class, and details are concrete implementation classes
-
The purpose of using interfaces or abstract classes is to create specifications that do not involve any concrete operations, leaving the task of presenting the details to their implementation classes
2. Application examples
Program Person to receive messages.
Scheme 2.1 a
class Email {
public String getInfo(a) {
return "Email message: Hello,world"; }}// Complete the function for Person to receive messages
// Mode 1 analysis
//1
//2. If the object we get is wechat, SMS, etc., then add a new class, and Perons also need to add corresponding receiving methods
//3. 解决 方 法 : introduce an abstract interface IReceiver, representing the receiver, so that the Person class depends on the interface IReceiver
// Since Email, WeiXin, etc., belong to the receiver scope, it is ok to implement the IReceiver interface respectively, so we rely on the inversion principle
class Person {
public void receive(Email email ) { System.out.println(email.getInfo()); }}Copy the code
test
public static void main(String[] args) {
Person person = new Person();
person.receive(new Email());
}
Copy the code
2.2 Scheme 2 (Dependency Reversal)
// Define the interface
interface IReceiver {
public String getInfo(a);
}
class Email implements IReceiver {
public String getInfo(a) {
return "Email message: Hello,world"; }}// Add wechat
class WeiXin implements IReceiver {
public String getInfo(a) {
return "Wechat message: Hello, OK"; }}2 / / way
class Person {
// Here we are relying on the interface
public void receive(IReceiver receiver ) { System.out.println(receiver.getInfo()); }}Copy the code
test
public static void main(String[] args) {
// The client does not need to change
Person person = new Person();
person.receive(new Email());
person.receive(new WeiXin());
}
Copy the code
3. Three ways of dependency transmission and application cases
As interface
Constructor pass
Setter pass
3.1 Interface Transfer
// Switch interface
interface IOpenAndClose {
public void open(ITV tv); // Abstract method, receive interface
}
interface ITV { / / the ITV interface
public void play(a);
}
class ChangHong implements ITV {
@Override
public void play(a) {
System.out.println("Changhong TV, turn it on."); }}// Implement the interface
class OpenAndClose implements IOpenAndClose {
public void open(ITV tv) { tv.play(); }}Copy the code
test
public static void main(String[] args) {
ChangHong changHong = new ChangHong();
OpenAndClose openAndClose = new OpenAndClose();
openAndClose.open(changHong);
}
Copy the code
3.2 Constructor pass
class ChangHong implements ITV {
@Override
public void play(a) {
// TODO Auto-generated method stub
System.out.println("Changhong TV, turn it on."); }}interface IOpenAndClose {
public void open(a); // Abstract methods
}
interface ITV { / / the ITV interface
public void play(a);
}
class OpenAndClose implements IOpenAndClose {
public ITV tv; / / members
public OpenAndClose(ITV tv) { / / the constructor
this.tv = tv;
}
public void open(a) {
this.tv.play(); }}Copy the code
test
public static void main(String[] args) {
ChangHong changHong = new ChangHong();
// Dependencies are passed through the constructor
OpenAndClose openAndClose = new OpenAndClose(changHong);
openAndClose.open();
}
Copy the code
3.3 Pass through setter methods
interface IOpenAndClose {
public void open(a); // Abstract methods
public void setTv(ITV tv);
}
interface ITV { / / the ITV interface
public void play(a);
}
class OpenAndClose implements IOpenAndClose {
private ITV tv;
public void setTv(ITV tv) {
this.tv = tv;
}
public void open(a) {
this.tv.play(); }}class ChangHong implements ITV {
@Override
public void play(a) {
// TODO Auto-generated method stub
System.out.println("Changhong TV, turn it on."); }}Copy the code
test
public static void main(String[] args) {
ChangHong changHong = new ChangHong();
OpenAndClose openAndClose = new OpenAndClose();
openAndClose.setTv(changHong);
openAndClose.open();
}
Copy the code
4. Notes and details that rely on the inversion principle
Low-level modules should have abstract classes or interfaces, or both, for better program stability.
Variables are declared as abstract classes or interfaces as possible, so that there is a buffer layer between our variable references and the actual object, which facilitates program expansion and optimization
Inheritance follows the Richter substitution principle