设计模式6大原则:里氏置换原则

前端之家收集整理的这篇文章主要介绍了设计模式6大原则:里氏置换原则前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。


里氏置换原则(Liskov Substitution Principle),简称LSP

定义:

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

所有引用基类的地方必须能够透明的使用其子类对象。

也就是说,只要父类出现的地方子类就能够出现,而且替换为子类不会产生任何错误或异常。但是反过来,子类出现的地方,替换为父类就可能出现问题了。

这个原则是为良好的继承定义一个规范,简单的讲,有4层含义:

一、子类必须完全实现父类方法

定义一个抽象类

 
 
  1. publicabstractclassViewPoint{
  2. //去丽江旅游
  3. publicabstractvoidwhere();
  4. }

下面两个类是实现这个抽象类

classLijiangextendsViewPoint{ 
  
  
  • @Override
  • voidwhere(){
  • System.out.println("欢迎来到丽江...");
  • }
  • }
  • classZhangjiajieextendsViewPoint{
  • @Override
  • voidwhere(){
  • System.out.println("欢迎来到张家界...");
  • }
  • }
  • 人物是涂涂,在里面设置类类型来传递参数。此时涂涂要去的旅游景点还是抽象的

    classTutu{ 
      
      
  • //定义要旅游的景点
  • privateViewPointviewpoint;
  • //涂涂要去的景点
  • voidsetViewPoint(ViewPointviewpoint)
  • {
  • this.viewpoint=viewpoint;
  • }
  • voidtravelTo()
  • {
  • System.out.println("涂涂要去旅游了");
  • viewpoint.where();
  • }
  • }
  • 场景类。设置具体要去的景点

    classSence{ 
      
      
  • staticvoidmain(Stringargs[])
  • {
  • Tutututu=newTutu();
  • //设置要去的旅游景点
  • tutu.setViewPoint(newLijiang());
  • tutu.travelTo();
  • }
  • }
  • 运行结果:

    涂涂要去旅游了
    欢迎来到丽江...

    二、子类可以有自己的特性

    也就是说在类的子类上,可以定义其他的方法属性

    三、覆盖或者实现父类方法时输入参数可以被放大

    父类能够存在的地方,子类就能存在,并且不会对运行结果有变动。反之则不行。

    父类,say()里面的参数是HashMap类型,是Map类型的子类型。(因为子类的范围应该比父类大)

    importjava.util.Collection; 
      
      
  • importjava.util.HashMap;
  • classFather{
  • publicCollectionsay(HashMapmap)
  • {
  • System.out.println("父类被执行...");
  • returnmap.values();
  • }
  • }
  • 子类,say()里面的参数变成了Map类型,Map范围比HashMap类型大,符合LSP原则。注意这里的say不是覆写父类的say,因为参数类型不同。而是重载。

    importjava.util.Map; 
      
      
  • /*
  • *子类继承了父类的所有属性
  • */
  • classSonextendsFather{
  • //方法输入参数类型
  • publicCollectionsay(Mapmap)
  • {
  • System.out.println("子类被执行...");
  • 场景类

    importjava.util.HashMap; 
  • classHome{
  • voidmain(Stringargs[])
  • {
  • invoke();
  • }
  • voidinvoke()
  • {
  • //父类存在的地方,子类就应该能够存在
  • //Fatherf=newFather();
  • Sons=newSon();
  • HashMapmap=newHashMap();
  • //f.say(map);
  • s.say(map);
  • }
  • }
  • 无论是用父类还是子类调用say方法,得到的结果都是

    父类被执行...

    但是,如果将上面Father里的say参数改为Map,子类Son里的say参数改为HashMap,得到的结果就变成了

    f.say(map)结果:父类被执行...

    s.say(map)结果: 子类被执行...

    这样会造成逻辑混乱。所以子类中方法的前置条件必须与父类中被覆写的前置条件相同或者更宽。

    四、覆写或者实现父类方法输出结果可以被缩小

    其实与上面的类似,也就是父类能出现的地方子类就可以出现,而且替换为子类不会产生任何错误或者异常,使用者也无需知道是父类还是子类。但是反过来就不行了,有子类出现的地方,父类未必就适应。(毕竟子类的范围要>=父类的范围)

    猜你在找的设计模式相关文章