Introduce a,

It’s easy to write code where the caller is dependent on a concrete implementation class, and when the requirements change and the concrete implementation class must be modified, the caller must also be affected to make the change, which is absurd. To solve this problem, the DIP: Dependence Inversion Principle came into being.

Second, the definition of

  • The high-level module (the calling side) should not depend on the low-level module (the concrete implementation class); both should depend on its abstraction
  • Abstractions should not depend on details
  • Details should depend on abstractions

Three, use

Take, for example, the scenario where the phone receives a message

/** * SMS */
public class Sms {

    public String getMessage(a) {
        return "Text message: Hello World!; }}/** * mobile phone */
public class Phone {

    public void receive(Sms sms) {
        if(sms ! =null) { String message = sms.getMessage(); System.out.println(message); }}}public class DependenceInversionPrinciple {

    public static void main(String[] args) {
        Phone phone = new Phone();
        phone.receive(newSms()); }}Copy the code

From the above code, it can be seen that the mobile Phone can receive Sms messages at the beginning, which meets the requirements. However, with the continuous improvement of the function of the mobile Phone, it can receive email, wechat and other messages. At this time, the above code is not satisfied, because the Phone’s receive method depends on specific details, which can only receive one Sms object. If you want to receive any other messages, you have to change this, and it’s not worth it. Because SMS, email, wechat and so on are all messages, the receiving message can be abstracted into an interface to cope with the changes of the receiving message.

/** * Abstract interface for receiving messages */
public interface IReceiver {

    String getMessage(a);
}

/** * mobile phone */
public class Phone {

    public void receive(IReceiver receiver) {
        if(receiver ! =null) { String message = receiver.getMessage(); System.out.println(message); }}}/** * SMS */
public class Sms implements IReceiver {

    @Override
    public String getMessage(a) {
        return "Text message: Hello World!; }}/** * Email */
public class Email implements IReceiver{

    @Override
    public String getMessage(a) {
        return "Email message: Hello World!"; }}/** * wechat */
public class WeiXin implements IReceiver {

    @Override
    public String getMessage(a) {
        return "Wechat message: Hello World!; }}public class DependenceInversionPrinciple {

    public static void main(String[] args) {
        Phone phone = new Phone();
        phone.receive(new Sms());
        phone.receive(new Email());
        phone.receive(newWeiXin()); }}Copy the code

After code optimization, as long as the message, you can through the implementation of IReceiver interface, it is easy to add a message can be received, without changing the original code, the phone wants to receive any messages can be.

Four,

Abstract things are much more stable than details. Therefore, the dependencies between modules should occur through abstraction, and the dependencies between implementation classes should not occur directly, but through interfaces or abstract classes.