Reliance inversion of the seven design principles of java, the principle of Liskov substitution (combination of text code to understand)

Reliance inversion of the seven design principles of java, the principle of Richter substitution, and the combination of text code to understand

Fight for if you like, cherish if you get, and forget if you miss. Life may not be perfect. Because of imperfection, we need to continue to work hard to create and strive. Time is life, so we must cherish our precious lives and persistently wait for every crossroad in our lives.

What are the seven design principles?

  • Single responsibility principle
  • Interface isolation principle
  • Dependence inversion (inversion) principle
  • Richter substitution principle
  • Principle of opening and closing
  • Dimit's Law
  • Synthetic reuse principle

Usually everyone understands the first six, and there is no synthetic reuse principle

Why use the seven design principles?

  • Code reusability (the same code does not need to be written multiple times);
  • Readability (standardization of programming, easy for other programmers to read and understand);
  • Extensibility (when new functions need to be added, it is very convenient, also called maintainability);
  • Reliability (when we add new functions, it will not affect the original functions);
  • Make the program present the characteristics of high cohesion and low coupling

Dependence inversion principle

Dependency inversion principle definition:

  • High-level modules should not rely on low-level modules, both should rely on their abstractions
  • The central idea of ​​relying on the principle of inversion is interface-oriented programming
  • The purpose of using interfaces or abstract classes is to formulate a good specification without involving any specific operations, and to delegate the detailed tasks to the implementation class to complete

The principle of reliance inversion is based on the design concept: Compared with the details, the abstract is much more stable. A framework based on abstraction is much more stable than a framework based on details . In Java, abstraction refers to the interface or abstract class, and the details are the specific implementation class

Ordinary code:

//输出消息
public class QQNews {
    
    
    public  void  run(){
    
    
        Log.i("Inversion","我是 QQ 发送的消息 ");
    }
}
//接收消息
public class Information {
    
    
    public void showInfo(QQNews qqNews){
    
    
        qqNews.run();
    }
}

//使用代码:
Information information = new Information();
information.showInfo(new QQNews());

problem:

  • Directly interact with the class, and the transmission message is relatively fixed
  • If I want to receive WeChat messages now, he can't receive them, because the code has been fixed, and now only accepts QQ messages.If I need to receive WeChat messages, I need to rewrite the method of receiving WeChat messages in the Information class.
  • There is no'buffer layer', the showInfo() method directly interacts with the QQNews class, and the'elasticity' is too low
  • Failure to comply with the principle of dependency inversion, the central idea of ​​the principle of dependency inversion is interface-oriented programming

Follow the dependency inversion principle code:

    ///接收的消息
public interface Iinversion {
    
    
    void run();
}
//QQ发送消息
public class QQNews implements Iinversion {
    
    
    @Override
    public void run() {
    
    
        Log.i("Inversion", "我是 QQ 发送的消息");
    }
}
//微信发送消息
public class WeChatNews  implements Iinversion{
    
    
    @Override
    public void run() {
    
    
        Log.i("Inversion","我是 微信 发送的消息");
    }
}

Code usage:

InversionBean inversionBean = new InversionBean();
inversionBean.run(new QQNews());
inversionBean.run(new WeChatNews());

advantage:

  • The client (InversionBean) only interacts with Iinversion (interface), the coupling is reduced, and the principle of interface-oriented programming in dependency inversion is strictly observed.
  • The code will not be fixed like the above, and there is no need to judge any conditions. I will receive QQ messages when I pass in QQ, and I will receive WeChat messages when I pass in WeChat. Compared with the details, abstract things are much more stable. Details Concrete implementation class

There are three ways to rely on the inversion principle:

method one:

Complete the transfer of the interface through the implementation class (QQNews) of the transfer interface (Iinversion)

public interface Iinversion {
    
    
    ///接收的消息
    void run();
}
public class QQNews implements Iinversion {
    
    
    @Override
    public void run() {
    
    
        Log.i("Inversion", "我是 QQ 发送的消息");
    }
}

Information information = new Information();
information.showInfo(new QQNews());

Way two:

Complete the transfer of the interface through the parameterized construction method

public interface Iinversion {
    
    
    ///接收的消息
    void run();
}

public class Information {
    
    

   Iinversion mIinversion;
   
    public Information(Iinversion iinversion) {
    
    
        mIinversion = iinversion;
    }
    public void showInfo(){
    
    
        mIinversion.run();
    }
}
//使用代码
Information information = new Information(new QQNews());
information.showInfo();

Way three:

Complete the interface transfer through the set method:

public interface Iinversion {
    
    
    ///接收的消息
    void run();
}
//传递消息 
public class QQNews implements Iinversion {
    
    
    @Override
    public void run() {
    
    
        Log.i("Inversion", "我是 QQ 发送的消息");
    }
}

public class Information {
    
    

    private Iinversion mIinversion;

    public void showInfo(){
    
    
        mIinversion.run();
    }
    public void setIinversion(Iinversion iinversion) {
    
    
         mIinversion =iinversion;
    }
}

//使用代码:
Information information = new Information();
information.setIinversion(new QQNews());
information.showInfo();

Richter substitution principle

basic introduction:

  • The Richter substitution principle was proposed by a woman in the Massachusetts Institute of Technology in 1988

The definition of the Richter substitution principle:

  • When inheriting, follow the Richter substitution principle and try not to override the method of the parent class in the subclass
  • All references to the base class must be able to transparently use the objects of its subclasses
  • The Richter substitution principle tells us that inheritance actually enhances the coupling of two classes. Under appropriate circumstances, problems can be solved through aggregation, composition, and dependency.
  • The parent class in the program can be replaced by the subclass

Failure to comply with Richter's substitution principle code:

public class ReplaceA {
    
    
    public int show(int a, int b){
    
    
        return  a+b;
    }
}

public class ReplaceB extends ReplaceA{
    
    
    @Override
    public int show(int a, int b){
    
    
        return  a-b;
    }
}

//使用代码:
 //里氏替换原则
ReplaceA replaceA = new ReplaceA();
ReplaceB replaceB = new ReplaceB();

Log.i("LiReplace","2 + 3 = "+replaceA.show(2,3)+"");
Log.i("LiReplace","2 + 3 = "+replaceB.show(2,3)+"");

As can be seen:

  • The output in class A is the sum of a + b
  • In class B, the show() method of class A is rewritten, and the output is ab

problem:

  • Because class B inherits class A, all methods in class A can be used in class B, which leads to a very high coupling of class B
  • And if there are some new methods added to class A, and class B is not used, it will also lead to increased coupling. If class B is not used, it can be called, does it increase the invasiveness of class B?
  • In this code, my original intention of replaceB was to call the show() method of the parent class to sum, but I forgot that I rewritten the show() method of the parent class to find the difference!

Hypothesis 1:
Now I forget that class B has overridden the method of class A. I use show() in class B. The result I want is summation . But, class B has overridden the method of class A, giving me Calculated as a difference , maybe you can find the problem by looking at the code, then I will give an example.

Hypothesis 2: There are now three classes of BCD, all inherited from Class A

If I change my requirements now, I want C for multiplication and D for division, how should I write it? Is it judged one by one? And the coupling is too high. Now A, B, C, D are four This class feels a bit confusing, this is one way, if there are a hundred and eighty, it is not directly cool o(╥﹏╥)o

Let's take a look at how to follow the Liskov substitution principle:

Follow the writing of Richter's substitution principle:

Solution:
Let Class A and Class B inherit a more popular parent class (BaseReplace)

public class BaseReplace {
    
    
}

public class ReplaceA extends BaseReplace{
    
    
    public int show(int a, int b){
    
    
        return  a+b;
    }
}

public class ReplaceB extends BaseReplace{
    
    
    public int show(int a, int b){
    
    
        return  a-b;
    }
}

UML图(2.1):

analysis:

  • Class A and Class B are completely unrelated, they are completely two separate modules,
  • No coupling at all

If you use the methods of class A in class B:

By way of combination/aggregation:

public class ReplaceB extends BaseReplace{
    
    
    ReplaceA replaceA = new ReplaceA();
    
    public int show(int a, int b){
    
    
        return  a-b;
    }

    public void useAshow(int a,int b ){
    
    
        replaceA.show(a,b);
    }
	public class ReplaceA extends BaseReplace{
    
    
	    public int show(int a, int b){
    
    
	        return  a+b;
	    }
	}
}
//使用代码
ReplaceB replaceB = new ReplaceB();
replaceB.useAshow(2,3)

You can see that the method of using combination in class B can still use the method of class A

This is the Richter substitution principle

Dependence inversion principle

Richter substitution principle

you may also like:

Go to the design pattern/design principle catalog page

Originality is not easy, remember to like it~

Guess you like

Origin blog.csdn.net/weixin_44819566/article/details/112187562