1. Basic introduction

Dependence Inversion Principle refers to:

  1. 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

  1. The central idea of dependency inversion is interface oriented programming

  2. 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

  3. 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

  1. As interface

  2. Constructor pass

  3. 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

  1. Low-level modules should have abstract classes or interfaces, or both, for better program stability.

  2. 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

  3. Inheritance follows the Richter substitution principle