文档章节

里氏代换原则

 沪江小虾米
发布于 2016/01/04 18:06
字数 583
阅读 8
收藏 0

        里氏代换原则讲的是基类和子类的关系。只有这种关系存在是里氏代换原则才存在,否则不存在。如果两个类A、B违反了里氏代换原则时刻从以下两个重构方案中选择一种:

    (1)创建一个新的抽象类C,作为两个具体类的超类,将A、B共同的行为移动到C中,从而解决二者行为是不一致的问题。

    (2)将B到A的继承关系改为委派关系。

本文例子描述的是第一种重构方法,第二种参见合成/聚合复用原则一文。

正方形可不可以被当做长方形的子类?

package Liskov.version1;

public class Rectangle {
	private long width;
	private long height;
	
	public long getWidth() {
		return width;
	}
	public void setWidth(long width) {
		this.width = width;
	}
	public long getHeight() {
		return height;
	}
	public void setHeight(long height) {
		this.height = height;
	}
}
package Liskov.version1;

public class Square {
	private long side;

	public long getSide() {
		return side;
	}

	public void setSide(long side) {
		this.side = side;
	}
	
}

因为此时的正方形类不是长方形类的子类,    因此不存在里氏代换关系。

那如果把正方形类定义为长方形类的子类呢,会有什么问题?

package Liskov.version2;

import Liskov.version1.Rectangle;

public class Square extends Rectangle{
	private int side;

	public int getSide() {
		return side;
	}

	public void setSide(int side) {
		this.side = side;
	}

}
package Liskov.version2;

import Liskov.version1.Rectangle;

public class smartTest {
	public void resize(Rectangle r){
		while(r.getHeight() <= r.getWidth())
			r.setWidth(r.getWidth()+1);
	}
}

如果smartTest类传入的是Rectangle对象,resize()方法将不断增加,直至超过长度而听下来;如果传入的是Square对象时,正方形少的边会不断增加直至溢出。


代码重构,依据白马黑马都是马的观点

package Liskov.version3;

public interface Quardrangle {
	public long getHeight();
	public long getWeight();
}
package Liskov.version3;

public class Rectangle implements Quardrangle {

	private long width;
	private long height;
	
	public long getWidth() {
		return width;
	}

	public long getHeight() {
		return height;
	}

	public void setWidth(long width) {
		this.width = width;
	}

	public void setHeight(long height) {
		this.height = height;
	}
}
package Liskov.version3;

public class Square implements Quardrangle{
	private long side;

	public long getSide() {
		return side;
	}

	public void setSide(long side) {
		this.side = side;
	}

	@Override
	public long getHeight() {
		// TODO Auto-generated method stub
		return side;
	}

	@Override
	public long getWidth() {
		// TODO Auto-generated method stub
		return side;
	}
	
}

    那么破坏里氏代换原则的问题是怎么避免的呢?秘密在于基类Quadrangle没有赋值方法,因此类似于smartTest的resize()方法不可能适用于Quadrangle类型,只能适用于不同的具体子类Rectangle和Square,因此里氏代换原则不可能被破坏。

© 著作权归作者所有

下一篇: "开-闭"原则
粉丝 0
博文 6
码字总数 2016
作品 0
杨浦
私信 提问
设计原则-里氏代换原则

里氏代换原则: 所有引用基类(父类)的地方, 必须能透明地使用其子类的对象. 里氏代换原则告诉我们, 在软件系统中, 将一个基类对象替换成它的子类对象, 程序将不会产生任何错误和异常, 反过来则...

hell03W
2016/11/10
35
0
Java开发中的23种设计模式详解

1、开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩...

大灰狼wow
2014/05/04
262
1
设计模式的6大原则:也是编程者编程时应该追求和遵循的

1、开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩...

十月阳光
2015/10/28
93
0
LSP (Liskov Substitution Principle)

(1) 应当尽量从抽象类继承,而不从具体类继承。   一般而言,如果有两个具体类A、B有继承关系,那么一个最简单的修改方案是建立一个抽象类C,然后让类A和B成为抽象类C的子类。即如果有一个由...

freeframe
2012/09/20
65
0
java设计模式基础

设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模式...

Z-向上
2018/01/11
16
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 我,小小编辑,食人族酋长

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享娃娃的单曲《飘洋过海来看你》: #今日歌曲推荐# 《飘洋过海来看你》- 娃娃 手机党少年们想听歌,请使劲儿戳(这里) @宇辰OSC...

小小编辑
今天
466
10
MongoDB系列-- SpringBoot 中对 MongoDB 的 基本操作

SpringBoot 中对 MongoDB 的 基本操作 Database 库的创建 首先 在MongoDB 操作客户端 Robo 3T 中 创建数据库: 增加用户User: 创建 Collections 集合(类似mysql 中的 表): 后面我们大部分都...

TcWong
今天
19
0
spring cloud

一、从面试题入手 1.1、什么事微服务 1.2、微服务之间如何独立通讯的 1.3、springCloud和Dubbo有哪些区别 1.通信机制:DUbbo基于RPC远程过程调用;微服务cloud基于http restFUL API 1.4、spr...

榴莲黑芝麻糊
今天
9
0
Executor线程池原理与源码解读

线程池为线程生命周期的开销和资源不足问题提供了解决方 案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。 线程实现方式 Thread、Runnable、Callable //实现Runnable接口的...

小强的进阶之路
昨天
30
0
maven 环境隔离

解决问题 即 在 resource 文件夹下面 ,新增对应的资源配置文件夹,对应 开发,测试,生产的不同的配置内容 <resources> <resource> <directory>src/main/resources.${deplo......

之渊
昨天
29
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部