03 里氏替换原则

官方定义:

里氏替换原则(Liskov Substitution Principle,LSP)是由麻省理工学院计算机科学系教授芭芭拉·利斯科夫于 1987 年在"面向对象技术的高峰会议"(OOPSLA)上发表的一篇论文《数据抽象和层次》(Data Abstractionand Hierarchy)里提出的.

她在论文中提到:如果S是T的子类型,对于S类型的任意对象,如果将他们看作是T类型的对象,则对象的行为也理应与期望的行为一致

子类对象能够替换程序中父类对象出现的任何地方,并且保证原来程序的逻辑行为不变及正确性不被破坏。

如何理解里氏替换原则?

要理解里氏替换原则,其实就是要理解两个问题:

什么是替换?

什么是与期望行为一致的替换(Robert Martin所说的"必须能够替换")?

1 ) 什么是替换 ?

替换的前提是面向对象语言所支持的多态 特性,同一个行为具有多个不同表现形式或形态的能力。

2 ) 什么是与期望行为一致的替换?

在不了解派生类的情况下,仅通过接口或基类的方法,即可清楚的知道方法的行为,而不管哪种派生类的实现,都与接口或基类方法的期望行为一致。

不需要关心是哪个类对接口进行了实现,因为不管底层如何实现,最终的结果都会符合接口中关于方法的描述(也就是与接口中方法的期望行为一致).

或者说接口或基类的方法是一种契约,使用方按照这个契约来使用,派生类也按照这个契约来实现。这就是与期望行为一致的替换。

场景案例

比如在一个商城项目中,有3种促销活动:

1)PromotionalStrategy (满减活动,两百以上百八折)

2)RebateStrategy(打折活动)

3)ReduceStrategy(返现活动)

java 复制代码
public interface Istrategy {
	public double realPrice(double consumePrice);
}
public class PromotionalStrategy implements Istrategy {
	public double realPrice(double consumePrice) {
if (consumePrice > 200) {
return 200 + (consumePrice - 200) * 0.8;
} else {
return consumePrice;
}
}
}
public class RebateStrategy implements Istrategy {
private final double rate;
public RebateStrategy() {
this.rate = 0.8;
}
public double realPrice(double consumePrice) {
return consumePrice * this.rate;
}
}
public class ReduceStrategy implements Istrategy {
public double realPrice(double consumePrice) {
if (consumePrice >= 1000) {
return consumePrice - 200;
} else {
return consumePrice;
}
}
}

调用方为Context,在此类中使用接口定义了一个对象

java 复制代码
public class Context {
//使用基类定义对象变量
private Istrategy strategy;
// 注入当前活动使用的具体对象
public void setStrategy(Istrategy strategy) {
this.strategy = strategy;
}
// 计算并返回费用
public double cul(double consumePrice) {
// 使用具体商品促销策略获得实际消费金额
double realPrice =
this.strategy.realPrice(consumePrice);
// 格式化保留小数点后1位,即:精确到角
BigDecimal bd = new BigDecimal(realPrice);
bd = bd.setScale(1, BigDecimal.ROUND_DOWN);
return bd.doubleValue();
}
}

Context 中代码使用接口定义对象变量,这个对象变量可以是实现了lStrategy

接口的PromotionalStrategy、RebateStrategy 、 ReduceStrategy任意一个。

里氏代换原则与多态的区别 ?

虽然从定义描述和代码实现上 来看,多态和里式替换有点类似,但它们关

注的角度是不一样的。多态是面向对象编程的一 大特性,也是面向对象编

程语言的一种语法。它是一种代码实现的思路。而里式替换是一种 设计原

则,用来指导继承关系中子类该如何设计,子类的设计要保证在替换父类

的时候,不 改变原有程序的逻辑及不破坏原有程序的正确性。

里氏替换原则和依赖倒置 原则,构成了面向接口编程的基础,正因为里氏替换

原则,才使得程序呈现多样性。

相关推荐
Kerwin要坚持日更5 天前
一文讲解Java中的重载、重写及里氏替换原则
java·里氏替换原则
诸神缄默不语16 天前
里氏替换原则(Liskov Substitution Principle,LSP):面向对象设计的基本原则
开发语言·里氏替换原则
智驾21 天前
SOLID原则学习,里氏替换原则
c++·里氏替换原则·solid
ke_wu1 个月前
常见设计原则
接口隔离原则·依赖倒置原则·里氏替换原则·开闭原则·迪米特法则·单一职责原则
Danileaf_Guo1 个月前
MPLS小实验:利用LDP动态建立LSP
里氏替换原则
向宇it1 个月前
【从零开始入门unity游戏开发之——C#篇26】C#面向对象动态多态——接口(Interface)、接口里氏替换原则、密封方法(`sealed` )
java·开发语言·unity·c#·游戏引擎·里氏替换原则
向宇it1 个月前
【从零开始入门unity游戏开发之——C#篇23】C#面向对象继承——`as`类型转化和`is`类型检查、向上转型和向下转型、里氏替换原则(LSP)
java·开发语言·unity·c#·游戏引擎·里氏替换原则
Danileaf_Guo1 个月前
MPLS小实验:静态建立LSP
网络·里氏替换原则
huaqianzkh2 个月前
里氏替换原则:Java面向对象设计的基石
java·设计模式·里氏替换原则
瞎姬霸爱.3 个月前
设计模式-七个基本原则之一-里氏替换原则
java·设计模式·里氏替换原则