Java seven design principles of dependency inversion, Richter substitution principle, text code combined understanding

  • What are the seven design principles?
  • Why use seven design principles?
  • Dependency inversion principle
  • Richter’s substitution principle

Like to fight for, get to cherish, miss to forget. Life may not be perfect, but because it is not perfect, we need to constantly strive to create and strive. Time is life, so we must cherish the precious life, persistent waiting for every crossing in life.

What are the seven design principles?

  • Single responsibility principle
  • Interface Isolation Principle
  • Rely on the inversion principle
  • Richter’s substitution principle
  • The open closed principle
  • Demeter’s rule
  • Principle of composite reuse

The first six are generally understood and there is no synthetic reuse principle

Why use seven design principles?

  • Code reuse (you don’t have to write the same code more than once);
  • Readability (normative programming that is easy for other programmers to read and understand);
  • Extensibility (also called maintainability when new features need to be added);
  • Reliability (when we add new features, there is no impact on the original features);
  • The program presents high cohesion, low coupling and other characteristics

Dependency inversion principle

Definition of dependency inversion principle:

  • A high-level module should not depend on a low-level module; both should depend on its abstraction
  • The central idea of dependency inversion is interface oriented programming
  • The purpose of using an interface or abstract class is to create a specification that does not involve any concrete operations, leaving the details to the implementation class

The dependency inversion principle is based on the design idea that abstract things are more stable than details. Frameworks based on abstraction are much more stable than those based on detail. In Java, abstraction refers to an interface or abstract class, and details are concrete implementation classes

Common code:

// Outputs the message
public class QQNews {
    public  void  run(a){
        Log.i("Inversion"."I am the message sent by QQ"); }}// Receive the message
public class Information {
    public void showInfo(QQNews qqNews){ qqNews.run(); }}// Use code:
Information information = new Information();
information.showInfo(new QQNews());
Copy the code

Question:

  • Interact directly with classes and transfer messages more consistently

  • If I want to receive wechat messages now, he cannot, because the code has been fixed and only QQ messages are accepted now. If I need to receive wechat messages, I still need to rewrite the method of receiving wechat messages in the Information class.
  • There is no ‘buffer layer’, the showInfo() method interacts directly with the QQNews class and is too ‘elastic’
  • The dependency inversion principle is not followed, and the central idea of dependency inversion principle is interface oriented programming

Abide by the dependency inversion principle code:

    /// The received message
public interface Iinversion {
    void run(a);
}
//QQ sends messages
public class QQNews implements Iinversion {
    @Override
    public void run(a) {
        Log.i("Inversion"."I am the message sent by QQ"); }}// Wechat sends messages
public class WeChatNews  implements Iinversion{
    @Override
    public void run(a) {
        Log.i("Inversion"."I sent the message from wechat."); }}Copy the code

Code use:

InversionBean inversionBean = new InversionBean();
inversionBean.run(new QQNews());
inversionBean.run(new WeChatNews());
Copy the code

Advantages:

  • The client (VersionBean) only interacts with the Iinversion(interface), resulting in reduced coupling and adherence to the principles of interface-oriented programming in dependency inversion
  • 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 receive wechat messages when I pass in wechat. Abstract things are much more stable than details, which are concrete implementation classes

There are three methods of dependence inversion principle:

A:

Delivery of the interface is completed through the Iinversion implementation class QQNews

public interface Iinversion {
    /// The received message
    void run(a);
}
public class QQNews implements Iinversion {
    @Override
    public void run(a) {
        Log.i("Inversion"."I am the message sent by QQ");
    }
}

Information information = new Information();
information.showInfo(new QQNews());
Copy the code

Method 2:

Pass the interface through the parameter constructor

public interface Iinversion {
    /// The received message
    void run(a);
}

public class Information {

   Iinversion mIinversion;
   
    public Information(Iinversion iinversion) {
        mIinversion = iinversion;
    }
    public void showInfo(a){ mIinversion.run(); }}// Use the code
Information information = new Information(new QQNews());
information.showInfo();
Copy the code

Three:

Pass the interface through set:

public interface Iinversion {
    /// The received message
    void run(a);
}
// Pass the message
public class QQNews implements Iinversion {
    @Override
    public void run(a) {
        Log.i("Inversion"."I am the message sent by QQ"); }}public class Information {

    private Iinversion mIinversion;

    public void showInfo(a){
        mIinversion.run();
    }
    public void setIinversion(Iinversion iinversion) { mIinversion =iinversion; }}// Use code:
Information information = new Information();
information.setIinversion(new QQNews());
information.showInfo();
Copy the code

Richter’s substitution principle

Basic introduction:

  • The Richter substitution principle was developed in 1988 by a woman named Lee at the Massachusetts Institute of Technology

Richter’s substitution principle definition:

  • When inheriting, follow the Richter’s substitution principle and try not to override methods of the parent class in subclasses
  • All references to a base class must be able to transparently use objects from its subclasses
  • Richter’s substitution principle tells us that inheritance actually makes two classes more coupled, and can be solved by aggregation, composition, and dependency, where appropriate
  • A parent class in a program can be replaced by a subclass

Code not following Richter’s substitution principle:

public class ReplaceA {
    public int show(int a, int b){
        returna+b; }}public class ReplaceB extends ReplaceA{
    @Override
    public int show(int a, int b){
        returna-b; }}// Use code:
 // Richter's substitution principle
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) +"");
Copy the code

As can be seen:

  • In class A, the output is the sum of A plus b
  • The show() method of class A is overridden in class B to output a-b

Question:

  • Because class B inherits class A, all methods in class A can be used by class B, which results in very high coupling of class B
  • Moreover, if some new methods are added to class A, which are not used by class B, the coupling will also be improved. If they are not used by class B, they can still be called, which will improve the intrusion of class B
  • In this code, I replaceB meant to call the superclass’s show() method to sum, but I forgot that I overwrote the superclass’s show() method to get the difference!

Hypothesis 1: Now I forget that class B overrides the method of class A, so I use show() from class B and I want the sum, but class B overrides the method of class A and gives me the difference, so maybe you can look at the code and figure out the problem, so I’ll give you an example.

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

What if I change my requirements now, and I want class C to multiply and class D to divide? Judge one by one? And so write the coupling is too high, now A,B,C,D these four classes feel A little confused, this is A method, if there are hundred and eighty that is not directly cool cool O (╥﹏╥)o

Let’s see if we can write it in accordance with Richter’s substitution rule:

To follow Richter’s substitution rule:

Class A and class B share A common parent class (BaseReplace)

public class BaseReplace {}public class ReplaceA extends BaseReplace{
    public int show(int a, int b){
        returna+b; }}public class ReplaceB extends BaseReplace{
    public int show(int a, int b){
        returna-b; }}Copy the code

UML diagrams (2.1) :

Analysis:

  • Classes A and B are completely unrelated, completely separate modules,
  • There is no coupling at all

If you use class A methods in class B:

By means 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){
	        returna+b; }}}// Use the code
ReplaceB replaceB = new ReplaceB();
replaceB.useAshow(2.3)
Copy the code

You can see that if you use A composite method in class B, you can still use A method in class A

That’s the Richter substitution rule

Dependency inversion principle

Richter’s substitution principle

What do you like?

  • The Seven Java Design Principles of a Single responsibility, interface Isolation principle (Literal code combined understanding)
  • Demeter principle, Open and Close Principle, Composite reuse principle (literal code combination understanding)
  • Android Studio UML modeling

Go to the Design Patterns/Design Principles directory page

Original is not easy, remember to like oh ~