zoukankan      html  css  js  c++  java
  • 设计模式之里氏替换原则

      What 

      Liskov Substitution Principle(LSP),任何父类出现的地方,子类一定可以出现。

      Why

      LSP是OCP原则的规范。OCP原则的关键的是抽象,而继承关系又是抽象的一种具体表现。

      How

      当子类不能完整的实现父类父类的方法,那么建议断开父子关系,采用依赖,聚合,组合等关系替代继承。下面是一个经典例子,鸵鸟不是鸟

      抽象鸟类,这里我们认为鸟类都会飞,抽象方法是获取飞行速度

        abstract class Bird : IFLy
        {
            Wing[] wings;
            public Bird()
            {
                wings = new Wing[2];
            }
    
            protected abstract double GetFlightSpeed();
    
            //飞行一段距离所需时间
            public double Fly(double distance)
            {
                return distance / GetFlightSpeed();
            }
        }

      燕子类,飞行速度是120

     class Swallow : Bird
        {
            protected override double GetFlightSpeed()
            {
                return 120d;
            }
        }

      鸵鸟类,鸵鸟不会飞,那么飞行速度是0

        class Ostrich : Bird
        {
            protected override double GetFlightSpeed()
            {
                return 0d;
            }
        }

      客户端调用

        class Program
        {
            static void Main(string[] args)
            {
                Bird bird = new Swallow();
                Double distance = 100;
                string time = bird.Fly(distance).ToString();
                Console.WriteLine(time);
                Console.ReadLine();
            }
        }

      这样看是没有问题的,但是当换成下列这样的情况

        class Program
        {
            static void Main(string[] args)
            {
                Bird bird = new Ostrich();
                Double distance = 100;
                string time = bird.Fly(distance).ToString();
                Console.WriteLine(time);
                Console.ReadLine();
            }
        }

      这样就是违反了LSP,因为鸵鸟并不能实现所有的鸟类功能,因为它不会飞,所以没有飞行速度,那么将来客户端调用的使用,当成一种鸟类飞行,就会造成不可预知的错误。

      为什么会造成这样的情况,其实是因为抽象封装的时候出现了问题,从生态学上来说有翅膀、有羽毛等特点的就是鸟,那么会飞的鸟应该是鸟类的一个分支,所以我们应该重新划分类的职责范围

        abstract class Bird
        {
            Wing[] wings;
            public Bird()
            {
                wings = new Wing[2];
            }
        }
     abstract class FlyBird : Bird, IFLy
        {
            protected abstract double GetFlightSpeed();
    
            public double Fly(double distance)
            {
                return distance / GetFlightSpeed();
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                IFLy flyBird = new Swallow();
                Double distance = 100;
                string time = flyBird.Fly(distance).ToString();
                Console.WriteLine(time);
                Console.ReadLine();
            }
        }
  • 相关阅读:
    JAVA流操作
    Ubuntu 14.04 忘记root密码
    产出与产能要平衡-《高效能人士的七个习惯》随笔三
    重新认识自我-《高效能人士的七个习惯》随笔二
    高效能人士的七个习惯 随笔一
    松下A6伺服器通信设定
    未能加载文件或程序集 或它的某一个依赖项。试图加载格式不正确的程序。问题解决
    keil中出现Undefined symbol FLASH_PrefetchBufferCmd (referred from main.o)等问题解决办法
    c语言中static的用法,包括全局变量和局部变量用static修饰
    STM32启动文件详细解析(V3.5.0) 以:startup_stm32f10x_hd.s为例
  • 原文地址:https://www.cnblogs.com/XzcBlog/p/4191947.html
Copyright © 2011-2022 走看看