`
vking_wang
  • 浏览: 10543 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

六大设计原则总结:2)里氏替换原则 -Liskov Substitution Principle

 
阅读更多
LSP,Liskov Substitution Principle:

1) If for each object s of type S, there is an objectt of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when s is substituted fort when S is a subtype of T.

2) Functions that use pointers or references to base classes must be able to user objects of derived classes without knowing it.

所有引用基类的地方,都能透明地替换成其子类对象。只要父类能出现的地方,子类就可以出现。


引入里氏替换原则能充分发挥继承的优点、减少继承的弊端。

继承的优点:

  • 代码共享,减少创建类的工作量;每个子类都有父类的方法和属性;
  • 提高代码重用性;
  • 子类可以形似父类,但又异于父类;
  • 提高代码可扩展性;
  • 提高产品开放性。

继承的缺点:

  • 继承是侵入性的——只要继承,就必须拥有父类的属性和方法;
  • 降低代码的灵活性——子类必须拥有父类的属性和方法,让子类自由的世界多了些约束;
  • 增强了耦合性——当父类的属性和方法被修改时,必须要考虑子类的修改。


示例(继承的缺点):

原有类A,实现减法功能:

    class A{  
        public int func1(int a, int b){  
            return a-b;  
        }  
    }  
      
    public class Client{  
        public static void main(String[] args){  
            A a = new A();  
            System.out.println("100-50="+a.func1(100, 50));  
            System.out.println("100-80="+a.func1(100, 80));  
        }  
    }  


新增需求:新增两数相加、然后再与100求和的功能,由类B来负责

    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;  
        }  
    }  
      
    public class Client{  
        public static void main(String[] args){  
            B b = new B();  
            System.out.println("100-50="+b.func1(100, 50));  
            System.out.println("100-80="+b.func1(100, 80));  
            System.out.println("100+20+100="+b.func2(100, 20));  
        }  
    }  

OOPS! 原本运行正常的相减功能发生了错误。原因就是类B在给方法起名时无意中重写了父类的方法!



问题由来:

有一功能P1,由类A完成。现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成。新功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,有可能会导致原有功能P1发生故障。


解决方案:

LSP为继承定义了一个规范,包括四层含义:


1)子类必须完全实现父类的方法

如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生畸变;则建议不要用继承,而采用依赖、聚集、组合等关系代替继承。


例如:父类AbstractGun有shoot()方法,其子类ToyGun不能完整实现父类的方法(玩具枪不能射击,ToyGun.shoot()中没有任何处理逻辑),则应该断开继承关系,另外建一个AbstractToy父类。


2)子类可以有自己得个性

即,在子类出现的地方,父类未必就能替代。


3)重载或实现父类方法时,输入参数可以被放大(入参可以更宽松)

否则,用子类替换父类后,会变成执行子类重载后的方法,而该方法可能“歪曲”父类的意图,可能引起业务逻辑混乱。


4)重写或实现父类方法时,返回类型可以被缩小(返回类型更严格)


建议:

在实际编程中,我们常常会通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的几率非常大。

父类中凡是已经实现好的方法(相对于抽象方法而言),实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些契约,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。而里氏替换原则就是表达了这一层含义。


里氏替换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。


Q:

LSP如何减少继承的弊端?


分享到:
评论

相关推荐

    Java_面向对象设计原则总结

    2 里氏替换原则-Liskov Substitution Principle (LSP) 3 接口分隔原则-Interface Segregation Principle (ISP) 4 单一职责原则-Single Responsibility Principle (SRP) 5 开闭原则-The Open-Closed ...

    里氏替换原则Demo

    里氏替换原则(Liskov Substitution Principle,简称LSP)是面向对象设计的基本原则之一,它是由美国计算机科学家芭芭拉·里科夫(Barbara Liskov)提出的。这个原则强调的是在软件工程中,子类型必须能够替换它们的...

    OO设计原则-里氏替换原则

    其中,里氏替换原则(Liskov Substitution Principle, LSP)是一项非常重要的原则,它确保了子类可以替换其基类而不破坏程序的正确性。本文将深入探讨里氏替换原则的核心概念及其应用场景,帮助读者理解这一原则的...

    里氏替换原则精讲

    里氏替换原则(Liskov Substitution Principle, LSP),是由麻省理工学院计算机科学实验室的芭芭拉·里斯科夫(Barbara Liskov)教授在1987年的OOPSLA大会上发表的文章《Data Abstraction and Hierarchy》中首次提出...

    13丨软件设计的里氏替换原则:正方形可以继承长方形吗?.pdf

    里氏替换原则(Liskov Substitution Principle,简称LSP)是面向对象设计的基本原则之一,由Barbara Liskov在1988年提出。该原则指出,子类型必须能够替换它们的基类型而不影响程序的正确性。这意味着在软件系统中,...

    深入理解JavaScript系列(8) S.O.L.I.D五大原则之里氏替换原则LSP

    前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第3篇,里氏替换原则LSP(The Liskov Substitution Principle )。 英文原文:...

    里氏代换原则案例程序LSP.zip

    里氏代换原则(Liskov Substitution Principle,简称LSP)是面向对象设计的基本原则之一,由芭芭拉·里科夫(Barbara Liskov)在1988年提出。该原则规定,子类必须能够替换它们的基类,并且在软件系统中不会产生任何...

    设计模式六大原则

    #### 二、里氏代换原则(Liskov Substitution Principle) **含义:** 里氏代换原则由Liskov女士提出,她指出子类必须能够替换它们的基类,即子类可以替换任何基类能够出现的地方,并且经过替换后,代码仍然能够...

    OOD面试应对方法 SOLID原则.mp4

    应届生及亚马逊面试必考,IT求职必备基础。...L - Liskov substitution principle 里氏替换原则 I - Interface segregation principle 接口分离原则 D - Dependency Inversion Principle 依赖反转原则

    24种设计模式C#版

    2、里氏替换原则【LISKOV SUBSTITUTION PRINCIPLE】:继承与派生的规则.(子类可替换父类) 3、依赖倒转原则【DEPENDENCE INVERSION PRINCIPLE】:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该...

    设计模式之里氏转换原则

    里氏转换原则(Liskov Substitution Principle,简称LSP)是面向对象设计的基本原则之一,它是SOLID原则中的L原则。这个原则是由Barbara Liskov在1987年提出的,它规定子类型必须能够替换它们的基类型,而不影响程序...

    设计模式六大原则与类的六种关系

    2. 里氏替换原则(Liskov Substitution Principle) 里氏替换原则是指继承时,不要重写或重载父类方法。继承是一种机制,使得子类可以继承父类的特性,但这并不意味着子类可以随意地修改父类的方法。 3. 依赖倒置...

    7里氏替换原则-课程内容.rar

    里氏替换原则(Liskov Substitution Principle,简称LSP)是面向对象设计的基本原则之一,由美国计算机科学家Barbara Liskov在1988年提出。这一原则是类型继承概念的重要基石,它规定了子类型必须能够替换掉它们的基...

    面向对象六大设计原则

    2、里氏替换原则(Liskov Substitution Principle,LSP) 3、依赖倒置原则(Dependence Inversion Principle,DIP) 4、接口隔离原则(Interface Separate Principle,ISP) 5、合成/聚合复用原则(Composite/...

    java面向对象设计的六大原则

    以下将详细介绍面向对象设计的六大原则:单一职责原则(Single Responsibility Principle, SRP)、开放封闭原则(Open-Closed Principle, OCP)、里氏替换原则(Liskov Substitution Principle, LSP)、依赖倒置原则...

    JAVA六大原则代码.zip

    里氏替换原则(Liskov Substitution Principle,LSP):子类应该能够替换掉父类并且工作正常,即子类必须能够完全替代父类的功能而不产生错误。这个原则保证了代码的可靠性和稳定性。 接口隔离原则(Interface ...

    设计模式总结

    里氏替换原则(Liskov Substitution Principle,LSP) 只要父类出现的地方都可以用子类替换。 依赖倒置原则(Dependece Inversion Principle,DIP) 面向接口编程。细节应该依赖抽象。 依赖可以传递。 依赖有三...

    六大设计原则,一些小例子(通俗易懂)

    3. 里氏替换原则(Liskov Substitution Principle, LSP) 里氏替换原则规定,子类型必须能够替换掉它们的基类型,并且在任何使用基类型的地方,都可以安全地使用子类型。例如,如果你有一个动物接口,狗和猫都是它...

    24种设计模式介绍与6大设计原则

    2、里氏代换原则(Liskov Substitution Principle) 里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用...

Global site tag (gtag.js) - Google Analytics