《设计模式之禅》六大设计原则(二)里氏替换原则

  • (二) 里氏替换原则(LSP-Liskov Substitution Princle)
  1. 概念:所有引用基类的地方都必须能透明的使用其子类(通俗的说就是父类出现的地方子类就可以出现,反之不一定成立)
  2. 示例:如图2-1一个简单的CS士兵与枪的示例,soldier建立与抽象Gun的联系,等到具体的场景类Client创建时,才创建AbstractGun的具体子类,示例代码:
    public class Client{
    Soldier sanMao=new Soldier();
    sanMao.setGun(new Rifle());
    sanMao.killEnemy();
    }

             
                                            图2-1
    使用原则:在类中调用其他的类时务必要使用父类或接口,如果不能使用父类或接口,则类的设计已经违背了LSP原则。
  3. 示例引申:
            如果有了一把玩具枪ToyGun,它在形状声音等都和真枪相似(假设AbstractGun中有描述形状和声音的属性),但是不能shoot杀人,该如何进行设计?两种解决办法,在Soldier类中增加InstanceOf的判断,如果为玩具枪则不能杀人,如果是这样则所有与AbstractGun有关联的类,都必须增加这一判断条件;第二种,ToyGun脱离继承,建立一个独立的父类,为了实现代码复用,可以与AbstractGun建立关联委托关系,如图2-2所示

                                                            图2-2
    如果子类不能完整的实现父类的方法,或者父类的某些方法在子类中已经发生了“畸变”,则建议断开父子继承关系,采用依赖、聚合、组合等关系来代替继承。
        实际上,这就衍生出了另一个设计模式的关键词Delegate即委派,该设计模式主要的应用场景为由于敏捷编程的兴起,重构技术也得到了大家的广泛使用;要使用重构,其中的一个重要原则是:使用组合代替聚合,这样才能方便重构。使用组合,最终是要使用到委派技术了。同时,我们经常有这样的一些需求,我们只想继承一个类的部分功能,而另外一部分功能是我们不想要、甚至是对我们有害的功能,这时候,我们只能使用委派技术,而不能使用继承了。
        基于上面的一些分析,我们知道,继承和委派技术都能扩展一个类,使它拥有另外一个类的部分或者全部功能。但委派技术更为灵活,它可以使得一个类可以全部或部分的扩展得到另一个类的功能,而继承只能是全盘接收。网址http://java.chinaitlab.com/advance/750844.html给出了为什么java语言强调委派比较少的原因,以及委派模式在Groovy语言中的应用。
  4. 实施原则
    (1)子类在实现或覆盖父类的方法时,输入参数可以被放大。
    public class Father{
          public Collection doSomething(HashMap map){
          System.out.println("父类被执行");
          return map.values();
     }
    }
    public class Son extends Father{
          public Collection doSomething(Map map){
          System.out.println("子类被执行");
          return map.values();
     }
    }
    public class Client{
    public static void invoker(){
    //父类存在的地方
    Father f= new Father();
    HashMap map= new HashMap();
    f.doSomething(map);
    }
    public static void main(String[] args){
    invoker();
    }
    }
    以上代码输出为“父类被执行”,如果将父类存在的地方换成Son,则同样输出“父类被执行”,该逻辑是合理的,遵循LSP原则,若将二者输入参数尽心调换,即Father类doSomething(Map map),Son类为doSomething(HashMap map),则执行结果为“子类被调用了”。
    (2)子类在实现或覆盖父类的方法时,返回结果可以被缩小,代码不在赘述。
  5. 最佳实践做法为:尽量减少子类的个性,一旦子类拥有个性,则很难和父类进行调和。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值