面向对象设计原则三:里氏替换原则(LSP)
里氏替换原则(LSP)
定义:在任何父类出现的地方都可以用它的子类类替换,且不影响功能。
解释说明:
其实LSP是对开闭原则的一个扩展,在OO思想中,我们知道对象是由一系列的状态和行为组成的,里氏替换原则说的就是在一个继承体系中,对象应该具有共同的外在特性,使用LSP时,如果想让我们的程序达到一个父类出现的地方都可以用它的子类来替换且不影响功能,那么这个父类也应该尽量声明出子类所需要的一些公共的方法,父类被子类替换之后,会比较顺利,那么为什么说它是对开闭原则的一个扩展呢?因为我们在开闭原则中说尽量使用接口和抽象类,当然这个抽象类和接口也应该尽量定义得完整,这样我们这个接口和抽象类会比较稳定,这样既符合了开闭原则也满足了里氏替换原则。
错误案例1:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace 里氏替换原则
{
/// <summary>
/// 鸟类
/// </summary>
public class Bird
{
/// <summary>
/// 吃的方法
/// </summary>
public void Eat()
{ } /// <summary>
/// 飞的方法
/// </summary>
public void Fly()
{ }
} /// <summary>
/// 定义一个企鹅类继承鸟类
/// </summary>
public class Penguin : Bird
{ } public class Test
{
public static void ShowFly(Bird bird)
{
bird.Fly();
} public static void Main()
{
ShowFly(new Penguin());
}
}
}
解释说明:
在上面的代码中,定义了一个鸟类,企鹅类继承自鸟类。鸟类里面有飞的方法,而企鹅不会飞,所以上面的代码违反了里氏替换原则。
错误案例2:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace 里氏替换原则
{
/// <summary>
/// 定义一个父类宠物类
/// </summary>
public class Pet
{
} /// <summary>
/// 定义一个企鹅类继承自宠物类
/// </summary>
public class PenguinDemo : Pet
{
/// <summary>
/// 游泳的方法
/// </summary>
public void Swiming()
{
Console.WriteLine("可爱企鹅在游泳");
}
} /// <summary>
/// 定义一个海豚类继承自宠物类
/// </summary>
public class Dolphin : Pet
{
/// <summary>
/// 玩游戏的方法
/// </summary>
public void PlayGame()
{
Console.WriteLine("神奇泡泡打砖块");
}
} /// <summary>
/// 测试类
/// </summary>
public class Test
{
public static void ShowPlay(Pet pet)
{
if (pet is PenguinDemo)
{
//类型转换
PenguinDemo pen = (PenguinDemo)pet;
pen.Swiming();
}
if (pet is Dolphin)
{
//类型转换
Dolphin dol = (Dolphin)pet;
dol.PlayGame();
}
}
}
}
解释说明:
如果把河豚、企鹅当做宠物,我们可以定义一个宠物类,然后,让这些宠物继承这个类,我们知道每种宠物我们跟他玩耍的方式是不一样的。比如。企鹅有游泳的方法,河豚有游戏的方法,根据这个需求,我们设计一个系统,编写一个宠物类,让企鹅继承这个宠物类,在企鹅类里创建一个游泳的方法,这个方法不能放到宠物类里面,因为并不是所有宠物都会游泳。编写河豚类时,同样让他继承宠物类,在河豚类里面编写一个游戏的方法,这个时候客户端程序在使用宠物类和它的子类的时候,就需要做判断,具体是哪个子类,我们通过宠物类是无法调用具体的方法,要做一个判断和转型,如果在加一个狗类,狗类也会有一个独立的方法,要修改之前的代码(使用宠物类和它的子类的时候,要增加判断是狗类),这很明显不符合开闭原则,也不可能符合里氏替换原则,因为这里面的任何一个宠物都无法替换他的父类,因为他们的行为是不一样的,代码的可维护性和重用性很差!
代码下载链接:http://files.cnblogs.com/files/dotnet261010/OO%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99.rar
面向对象设计原则三:里氏替换原则(LSP)的更多相关文章
- C# 实例解释面向对象编程中的里氏替换原则
在面向对象编程中,SOLID 是五个设计原则的首字母缩写,旨在使软件设计更易于理解.灵活和可维护.这些原则是由美国软件工程师和讲师罗伯特·C·马丁(Robert Cecil Martin)提出的许多原 ...
- IOS设计模式的六大设计原则之里氏替换原则(LSP,Liskov Substitution Principle)
定义 里氏替换原则的定义有两种,据说是由麻省理工的一位姓里的女士所提出,因此以其名进行命名. 定义1:如果对一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1所定义的程序P中在o1全都替换 ...
- 深入理解JavaScript系列(8):S.O.L.I.D五大原则之里氏替换原则LSP
前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第3篇,里氏替换原则LSP(The Liskov Substitution Principle ). 英文原文:http ...
- Java设计原则之里氏替换原则
里氏代换原则由2008年图灵奖得主.美国第一位计算机科学女博士Barbara Liskov教授和卡内基·梅隆大学Jeannette Wing教授于1994年提出.其严格表述如下:如果对每一个类型为S的 ...
- 【面向对象设计原则】之里氏替换原则(LSP)
里氏代换原则由2008年图灵奖得主.美国第一位计算机科学女博士Barbara Liskov教授和卡内基·梅隆大学Jeannette Wing 教授于1994年提出,所以使用的是这位女博士的性命名的一个 ...
- 设计模式学习--面向对象的5条设计原则之Liskov替换原则--LSP
一.LSP简介(LSP--Liskov Substitution Principle): 定义:如果对于类型S的每一个对象o1,都有一个类型T的对象o2,使对于任意用类型T定义的程序P,将o2替换为o ...
- S.O.L.I.D: PHP 面向对象设计的五个基准原则
S.O.L.I.D 是首个 5 个面向对象设计 (OOD) 准则的首字母缩写,这些准则是由 Robert C. Martin 提出的,他更为人所熟知的名字是 Uncle Bob. 这些准则使得开发出易 ...
- [OOD]违反里氏替换原则的解决方案
关于OOD中的里氏替换原则,大家耳熟能祥了,不再展开,可以参考设计模式的六大设计原则之里氏替换原则.这里尝试讨论常常违反的两种形式和解决方案. 违反里氏替换原则的根源是对子类及父类关系不明确.我们在设 ...
- 【C#设计模式】里氏替换原则
今天,我们再来学习 SOLID 中的"L"对应的原则:里式替换原则. 里氏替换原则 里氏替换原则(Liskov Substitution Principle):派生类(子类)对象能 ...
随机推荐
- Android 代码实现来电拦截
为了更好地理解这个Demo,我先向大家介绍一下需求与功能. 需求: 每天都会有很多无聊的电话,比如推销商品等,占用我们大量时间不说,有时候还会打乱我们的思路,扰乱我们的正常生活.所以实现一个对某些号码 ...
- Cocos2d-x -- 如何让背景从上到下滚动
1. 首先,声明一个2个大小的sprite数组 class GameScreen : public cocos2d::Layer { public: ... cocos2d::Sprite *back ...
- 软件开发工具——Make
掌握Makefile的使用方法和工作流程: 掌握make工具变量的相关知识,包括其引用.定义及分类等: 掌握Makefile常见的函数含义: 掌握Makefile与shell命令行的通信方法: 掌握M ...
- Adobe Audition3.0 找不到所支持的音频设备 请检查您的音频设置
Adobe Audition 找不到所支持的音频设备 请检查您的音频设置 解决方案: 运行regedit,打开注册表编辑器,定位到 HKEY_CLASSES_ROOT\CLSID\{AB7 ...
- MS SQL得到指定日期的当月月末
MS SQL得到指定日期的当月月末 declare @ddate date ,,)) select @ddate --2016-01-31 declare @ddatetime datetime ,, ...
- CLightLock:一个简单AutoLock
原理: 标准的RAII, 利用构造函数进行加锁,利用析构函数进行解锁. #ifndef _C_LIGTHT_LOCK_HPP #define _C_LIGTHT_LOCK_HPP class CLig ...
- OFBiz:component-load.xml
component-load.xml定义了OFBiz的组件载入位置,默认的是通过目录来设置: <component-loader xmlns:xsi="http://www.w3.or ...
- 【转帖】阿里金融云:分布式服务注册中心(DSR)
https://www.cloud.alipay.com/docs/middleware/register/index.html 分布式服务注册中心(DSR) 分布式服务注册中心简介 服务注册中心 ( ...
- HttpSolrServer 实例管理参考,来自org.eclipse.smila.solr
http://dev.eclipse.org/svnroot/rt/org.eclipse.smila/trunk/core/org.eclipse.smila.solr/code/为什么要对实例管理 ...
- 【翻译】Android多线程下安全访问数据库
为了记录如何线程安全地访问你的Android数据库实例,我写下了这篇小小札记.文章中引用的项目代码请点击这里 假设你已编写了自己的 SQLiteOpenHelper. publicclas ...