美文网首页
设计模式-里氏替换原则

设计模式-里氏替换原则

作者: 小小小8021 | 来源:发表于2018-11-19 23:50 被阅读261次

    设计模式-里氏替换原则

    优点

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

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

    提供规范

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

    长方形是不是正方形

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


    image

    关系如上所示

    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的方法。
    如果代码更改如下更改
    让其两个都共同定义同一个父类即可

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

    改进如下

    image
    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

    相关文章

      网友评论

          本文标题:设计模式-里氏替换原则

          本文链接:https://www.haomeiwen.com/subject/ycizfqtx.html