Seis principios de diseño: el principio de sustitución de Richter

2.
Definición del Principio de sustitución de Liskov (LSP) : todas las referencias a la clase base deben poder usar de manera transparente el objeto de subclase
El Principio de sustitución de Liskov : es decir, cuando un objeto es reemplazado por su subclase en el programa En este momento, el programa puede continuar con el comportamiento original y no puede detectar la diferencia entre la runa y las subclases. Pero lo contrario no es cierto: si un programa usa una subclase, no es necesariamente aplicable a la clase padre.
Tomemos una computadora como ejemplo: una computadora tiene una CPU, una computadora es una entidad de programa, una CPU es la clase base que usa y una CPU tiene una subclase IntelCpu.
public  class Cpu { 

    public  void work () { 
        System.out.println ( "CPU 在 工作" ); 
    } 
} 
clase pública  IntelCpu extiende Cpu { 
    @Override public void work () { 
        System.out.println ( "英特尔 CPU 工作" ); 
    } 
} computadora de clase pública { CPU privada de la CPU; public void run () {
         this .cpu.work (); 
    } public Cpu getCpu () {
         return cpu;
     
 

    

     

     
    }

     public  void setCpu (CPU cpu) {
         this .cpu = cpu; 
    } 
}
La computadora depende de la clase principal. En este momento, la CPU se reemplaza con el tipo Intel, y la computadora aún puede funcionar normalmente. No nota ningún cambio, lo que está en línea con el principio de sustitución de Liskov.  
Y a la inversa, supongamos que hay una computadora ahora, solo puede funcionar con IntelCpu.
público  de clase IntelCpuComputer {
     privado CPU IntelCpu; 
    
    public  void run () {
         this .cpu.work (); 
    } 

    public IntelCpu getCpu () {
         return cpu; 
    } 

    public  void setCpu (IntelCpu cpu) {
         this .cpu = cpu; 
    } 
}
Si reemplaza IntelCpu con la CPU principal en este momento, la computadora no funcionará correctamente porque solo puede funcionar correctamente cuando se utiliza IntelCpu.
public  static  void main (String [] args) { 
      computadora IntelCpuComputer = nueva IntelCpuComputer (); 
      computer.setCpu ( nueva Cpu ()); // 报错 
  }
Como otro ejemplo, todos sabemos que los cuadrados son rectángulos especiales en matemáticas. ¿Podemos decir que los cuadrados son una subclase de rectángulos?  
Usamos código para representar cuadrados y rectángulos:
/ ** 
 * 长方形
 * @author ZhaoShuai 
 * @date Crear en 2020/4/12 
 * * / 
public  class Rectangle { 

    private Integer height;
    ancho entero privado ; 

    public Integer getHeight () {
         return height; 
    } 

    public  void setHeight (altura entera) {
         this .height = height; 
    } 

    public Integer getWidth () {
         return width; 
    } 

    public  void setWidth (ancho entero) {
         esto.width = ancho; 
    } 
} 
/ ** 
 * 正方形
 * @author ZhaoShuai 
 * @date Crear en 2020/4/12 
 * * / 
public  class Square { 
    
    private Integer side; 

    public Integer getSide () {
         return side; 
    } 

    public  void setSide (lado entero) {
         this .side = side; 
    } 
}
Todos sabemos que la clase principal se encapsula extrayendo las subclases. Del código anterior, podemos ver que la fórmula estructural del rectángulo y el cuadrado son diferentes. El rectángulo tiene los atributos de longitud y ancho, mientras que el cuadrado tiene el atributo de longitud variable. 
Por lo tanto, los cuadrados no son subclases de rectángulos. Por supuesto, también es posible forzar a los rectángulos a heredar como clases primarias, pero no heredamos por herencia. Este tipo de herencia por herencia no es parte del Principio de sustitución de Liskov.
paquete com.xiazhi.principle.lsp; 

/ ** 
 * @author ZhaoShuai 
 * @date Crear en 2020/4/12 
 * * / 
public  class SquareExtendsRectangle extiende Rectángulo { 

    lado entero privado ; 

    @Override 
    public  void setHeight (altura entera) {
         this .setSide (altura); 
    } 

    @Override 
    public  void setWidth (ancho entero) {
         this .setSide (ancho); 
    } 

    @Override 
    public Integer getHeight () {
         devolver  esto.getSide (); 
    } 

    @Override 
    public Integer getWidth () {
         devolver  este .getSide (); 
    } 

    public Integer getSide () {
         return side; 
    } 

    public  void setSide (lado entero) {
         this .side = side; 
    } 
}
Se puede ver que heredamos por la fuerza el rectángulo del cuadrado, y luego escribimos una clase de prueba:
 public  static  void main (String [] args) { 
        System.out.println ( "============ 长方形 ==============" ); 
        Rectángulo rectángulo = nuevo Rectángulo (); 
        rectangle.setHeight ( 10 ); 
        rectangle.setWidth ( 20 ); 
        imprimir (rectángulo); 

        System.out.println ( "============ 正方形 ==============" ); 
        Rectangle square = new SquareExtendsRectangle (); 
        square.setHeight ( 10 ); 
        imprimir (cuadrado); 

    } 

    vacío estático privado  print (Rectángulo rectángulo) { 
        System.out.println ( "高 :" + rectangle.getHeight ()); 
        System.out.println ( "宽 :" + rectangle.getWidth ()); 
    }
Después de probar, descubrimos que parece estar funcionando correctamente, en este momento agregamos otro método:
public  static  void main (String [] args) { 
        System.out.println ( "============ 长方形 ==============" ); 
        Rectángulo rectángulo = nuevo Rectángulo (); 
        rectangle.setHeight ( 10 ); 
        rectangle.setWidth ( 20 ); 
        prueba (rectángulo); 

        System.out.println ( "============ 正方形 ==============" ); 
        Rectangle square = new SquareExtendsRectangle (); 
        square.setHeight ( 10 ); 
        prueba (cuadrado); 

    } 

    vacío estático privado  print (Rectángulo rectángulo) { 
        System.out.println ( "高 :" + rectangle.getHeight ()); 
        System.out.println ( "宽 :" + rectangle.getWidth ()); 
    } 

    prueba de vacío estático privado  (rectángulo rectángulo) {
         while (rectangle.getWidth ()> = rectangle.getHeight ()) { 
            rectangle.setHeight (rectangle.getHeight () +1 ); 
            imprimir (rectángulo); 
        } 
    } 
Después de ejecutar, puede encontrar que el rectángulo puede funcionar normalmente, pero el cuadrado tendrá un bucle sin fin, por lo que esto no está en línea con el principio de sustitución de Liskov. Debido a que el objeto de subclase no se puede usar donde se hace referencia a la clase padre. 
En el diseño de la clase, de acuerdo con el principio de inversión de dependencia, debe usar clases o interfaces abstractas. Si no puede usar clases o interfaces abstractas, significa que el diseño viola el Principio de sustitución de Richter (LSP)

Supongo que te gusta

Origin www.cnblogs.com/Zs-book1/p/12714021.html
Recomendado
Clasificación