里氏替换原则是Barbara Liskov女士在1998年发表的ASD,具体的数学定义比较复杂,你可以查相关资料。它的白话翻译------》就是一个软件实体如果使用的是一个父类的话,那么一定要适用于子类,而且它察觉不出父类对象和子类对象的区别。也就是说,在软件里面,把父类都替换成它的子类,程序的行为没有变化(其实,就是多态)。

  里氏替换原则(LSP):子类型必须能够替换他们的父类型。

  ---里氏替换原则,使得开放-封闭原则成为了可能。对类本身修改关闭,对子类,派生类扩展开放!!!(当然依赖倒置原则也可以,它们是用接口实现。)

  ---一个应用实例:

  只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能真正的被复用,而子类也能够在父类的基础上增加新的行为。(比方说,猫是继承动物类的,以动物身份拥有吃eat,喝drink,跑run,叫shout等行为,可当某一天,我们需要狗,牛,羊也拥有类似的行为,由于他们都是继承于动物,所以除了更改实例化的地方程序其他处不需要改变)

public class Animal  //对修改关闭,对扩展开放
{
    public virtual void eat(){}
    public virtual void  drink(){}
    public virtual void run(){}
    public virtual void shout(){}
}

public class Dog:Animal  //扩展类,对扩展开放,本身不用改变
{  
    public override void shout()
    {  
        Console.WriteLine("我是狗") ;
    }
}

public class Cat:Animal 
{  
    public override void shout()
    {  
        Console.WriteLine("我是猫") ;
    }
}

//...,一堆扩展类
public class Program  //对修改关闭
{
    public Animal a1;
    public Program(Animal animal)
    {     
        if(animal!=null)
        {
            this.a1=animal;
        }
    }

    public void shout()
    {
        if(a1!=null)
        {
            a1.shout();
        }
        else
        {
            Console.WriteLine("传入对象为空!");
        }
    }
}

---下边是控制台主程序中,调用实例代码(需要更改的地方):

Animal dog=new Dog();
Animal cat=new Cat();
Program p=new Program(cat);
p.shout();  //输出,我是猫,如果想输出,我是狗,上边传入实例化对象dog,就可以了。
Console.ReadKey();

 

@总结:

1,看上去很不可思议,因为我们会发现在自己编程中常常会违反里氏替换原则,程序照样跑的好好的。所以大家都会产生这样的疑问,假如我非要不遵循里氏替换原则会有什么后果?

后果就是:你写的代码出问题的几率将会大大增加。

2,按LSP原则,则要注意:若子类不能完整地实现父类的方法(例如鸟类会飞,企鹅类继承了鸟类,但企鹅不会飞,这就是不能完整地实现父类的方法,所以企鹅类不能继承鸟类。),或者父类的某些方法在子类中发生畸变,则建议断开父子继承关系,采用依赖、聚集、组合等关系代替继承。

3,采用里氏替换原则的目的就是增强程序的健壮性,版本升级时也可以保持非常好的兼容性。即使增加子类,原有的子类也可以继续运行在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑。(多态!!!)

4,联系依赖倒置原则记忆!

 

posted on 2014-03-27 13:29  学到老死  阅读(251)  评论(0)    收藏  举报