• 设计模式-里氏替换原则


    设计模式-里氏替换原则

    优点

    面向对象的语言继承必不可少的,有如下优点

    1. 代码共享,减少创建类的工作量
    2. 提高代码的重用性
    3. 提高代码的可扩展性
    4. 提高代码的可扩展性
    5. 提高产品代码的开放性
    6. 继承侵入性 只要继承,必须拥有父类的内容
    7. 降低代码的灵活性,子类必须拥有父类的属性和方法
    8. 增强耦合性。

    提供规范

    里氏替换原则,为继承定义规范。

    长方形是不是正方形

    正方形是一种特殊的长方形,如果将正方形设计为长方形的子类,不符合里氏替换原则
    下方有三个类
    类图如下

    关系如上所示

    package demo1;
    
    public class SmartTest {
    	/*
    	 * 长方形的长增加超过宽
    	 * 
    	 * @param r
    	 * */
    	
    	public void resize(Rectangle r) {
    		while (r.getHeight() <= r.getWidth()) {
    			r.setHeight(r.getHeight() + 1);
    		}
    	}
    }
    
    package demo1;
    /*
     * 定义一个长方形类
     * @author ming
     * */
    
    public class Rectangle {
    	protected long width;	// 可以访问基类继承而来的,不能访问基类本身的,对同包内的可见,并且子类也可见
    	protected long height;
    	
    	public void setWidth(long width) {
    		this.width = width;
    	}
    	
    	public long getWidth() {
    		return this.width;
    	}
    	
    	public void setHeight(long height) {
    		this.height = height;
    	}
    	
    	public long getHeight() {
    		return this.height;
    	}
    }
    
    package demo1;
    /*
     * 定义一个正方形类继承自长方形类
     * 
     * @author ming
     * 
     * */
    public class Square extends Rectangle{
    	public void setWidth(long width, long height) {
    		this.width = width;
    		this.height = height;
    	}
    	
    	public long getWidth() {
    		return width;
    	}
    	
    	public void setHeight(long height, long width) {
    		this.height = height;
    		this.width = width;
    	}
    	
    	public long getHeight() {
    		return height;
    	}
    }
    

    在上面的三块代码中,当调用SmartTest类的resize方法的时候,如果传入的是父类,那么将会可以的,如果传入的是子类,正方形,那么将会不可以的。
    即。上方的为长方形行,正方形不行。
    所以上面的栗子不符合里氏替换原则。
    解决方法,使用继承时,要遵守里氏替换原则,类B继承类A时,不要重写父类A的方法,也不能重载父类A的方法。
    如果代码更改如下更改
    让其两个都共同定义同一个父类即可

    其中最上层的类为两个类的抽象类。

    改进如下

    package com.ming;
    
    /*
     * 定义一个四边形类,只有get方法set方法
     * @author ming
     * */
    public abstract class Quadrangle {
    	protected abstract long getWidth();
    	protected abstract long getHeight();
    }
    
    package com.ming;
    
    public class Rectangle extends Quadrangle {
    	private long width;
    	private long height;
    	
    	public void setWidth(long width) {
    		this.width = width;
    	}
    	
    	public long getWidth() {
    		return this.width;
    	}
    	
    	public void setHeight(long height) {
    		this.height = height;
    	}
    	
    	public long getHeight() {
    		return this.height;
    	}
    }
    
    package com.ming;
    
    public class Square extends Quadrangle{
    	private long width;
    	private long height;
    	
    	public void setWidth(long width) {
    		this.height = width;
    		this.width = width;
    	}
    	
    	public long getWidth() {
    		return this.,width;
    	}
    	
    	public void setHeight(long height) {
    		this.height = height;
    		this.width = height;
    	}
    	
    	public long getHeight() {
    		return this.height;
    	}
    }
    

    在上方的图中,由于两个为平级关系,所以父类的地方,换成子类也都可以。

    总结

    里氏替换原则;父类可以的地方,换成子类也同样可以。

    为什么要符合

    一个栗子

    package com.ming2;
    
    public class A {
    	public int func1(int a, int b) {
    		return a-b;
    	}
    }
    
    package com.ming2;
    
    public class B extends A{
    	public int func1(int a, int b) {
    		return a+b;
    	}
    	
    	public int func2(int a, int b) {
    		return func1(a,b)+100;	// 调用func1
    	}
    }
    

    在上方中,如果这样书写

    package com.ming2;
    
    public class Client {
    	public static void main(String[] args) {
    		B b = new B();
    		System.out.println(b.func1(100, 50));
    	}
    }
    

    就违反了里氏替换原则,即子类能使用的时候,父类也必须能使用。

    www.iming.info

    在无知的道路上缓步前行
  • 相关阅读:
    pm2
    php 基础知识
    EBADF, read
    php apache
    noah
    ejs
    node linux
    枚举系统进程
    c++ 进程权限的提升
    Liunx的目录结构
  • 原文地址:https://www.cnblogs.com/melovemingming/p/9986223.html
Copyright © 2020-2023  润新知