里氏替换原则原则
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
package top.fjy8018.designpattern.principle.liskovsubstitution.classdemo.after;
|
||||
|
||||
/**
|
||||
* 里氏替换原则:如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换为o2,程序P的行为没有发生变化,那么类型S是类型T的子类型
|
||||
* 即:所有使用父类对象的地方替换成子类对象依然正常运行
|
||||
*
|
||||
* @author F嘉阳
|
||||
* @date 2018-09-22 20:01
|
||||
*/
|
||||
public class ARectangle implements Quadrangle {
|
||||
private long length;
|
||||
|
||||
private long width;
|
||||
|
||||
@Override
|
||||
public long getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setWidth(long width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public void setLength(long length) {
|
||||
this.length = length;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package top.fjy8018.designpattern.principle.liskovsubstitution.classdemo.after;
|
||||
|
||||
/**
|
||||
* @author F嘉阳
|
||||
* @date 2018-09-22 20:03
|
||||
*/
|
||||
public class ASquare implements Quadrangle {
|
||||
private long sideLength;
|
||||
|
||||
@Override
|
||||
public long getWidth() {
|
||||
return sideLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength() {
|
||||
return sideLength;
|
||||
}
|
||||
|
||||
public void setLength(long sideLength) {
|
||||
this.sideLength = sideLength;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package top.fjy8018.designpattern.principle.liskovsubstitution.classdemo.after;
|
||||
|
||||
/**
|
||||
* 通过四边形接口连接,防止继承泛滥
|
||||
*
|
||||
* @author F嘉阳
|
||||
* @date 2018-09-22 20:11
|
||||
*/
|
||||
public interface Quadrangle {
|
||||
long getWidth();
|
||||
|
||||
long getLength();
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package top.fjy8018.designpattern.principle.liskovsubstitution.classdemo.before;
|
||||
|
||||
/**
|
||||
* 里氏替换原则:如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换为o2,程序P的行为没有发生变化,那么类型S是类型T的子类型
|
||||
* 即:所有使用父类对象的地方替换成子类对象依然正常运行
|
||||
*
|
||||
* @author F嘉阳
|
||||
* @date 2018-09-22 20:01
|
||||
*/
|
||||
public class Rectangle {
|
||||
private long length;
|
||||
private long width;
|
||||
|
||||
public long getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public void setLength(long length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public long getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setWidth(long width) {
|
||||
this.width = width;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package top.fjy8018.designpattern.principle.liskovsubstitution.classdemo.before;
|
||||
|
||||
/**
|
||||
* @author F嘉阳
|
||||
* @date 2018-09-22 20:03
|
||||
*/
|
||||
public class Square extends Rectangle {
|
||||
private long sideLength;
|
||||
|
||||
@Override
|
||||
public long getLength() {
|
||||
return sideLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* 覆盖了父类的实现,不满足里氏替换原则
|
||||
*
|
||||
* @param length
|
||||
*/
|
||||
@Override
|
||||
public void setLength(long length) {
|
||||
this.sideLength = length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getWidth() {
|
||||
return sideLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWidth(long width) {
|
||||
this.sideLength = width;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package top.fjy8018.designpattern.principle.liskovsubstitution.method.input.after;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @author F嘉阳
|
||||
* @date 2018-09-23 11:29
|
||||
*/
|
||||
@Slf4j
|
||||
class Base {
|
||||
|
||||
public void method(HashMap map) {
|
||||
log.info("父类被执行");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package top.fjy8018.designpattern.principle.liskovsubstitution.method.input.after;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 李氏转换原则要求方法入参必须比父类范围更宽,返回值必须比父类更窄
|
||||
*
|
||||
* @author F嘉阳
|
||||
* @date 2018-09-23 11:30
|
||||
*/
|
||||
@Slf4j
|
||||
class Child extends Base {
|
||||
|
||||
/**
|
||||
* 方法重写,入参必须等于父类或者比父类范围更宽
|
||||
* 而返回值比父类更窄已经交由IDE判断,若不符合,则编译不通过
|
||||
*
|
||||
* @param map
|
||||
*/
|
||||
@Override
|
||||
public void method(HashMap map) {
|
||||
log.info("子类HashMap入参方法被执行");
|
||||
}
|
||||
|
||||
/**
|
||||
* 方法重写,是子类额外的方法
|
||||
*
|
||||
* @param map
|
||||
*/
|
||||
public void method(Map map) {
|
||||
log.info("子类Map入参方法被执行");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package top.fjy8018.designpattern.principle.liskovsubstitution.method.input.before;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* @author F嘉阳
|
||||
* @date 2018-09-23 11:29
|
||||
*/
|
||||
@Slf4j
|
||||
class Base {
|
||||
|
||||
public void method(Map map) {
|
||||
log.info("父类被执行");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package top.fjy8018.designpattern.principle.liskovsubstitution.method.input.before;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @author F嘉阳
|
||||
* @date 2018-09-23 11:30
|
||||
*/
|
||||
@Slf4j
|
||||
class Child extends Base {
|
||||
|
||||
public void method(HashMap map) {
|
||||
log.info("子类HashMap入参方法被执行");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,23 +27,25 @@ public class JavaDiscountCourse extends JavaCourse {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取原价
|
||||
* 实现打折价格逻辑
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public BigDecimal getOriginPrice() {
|
||||
return super.getPrice();
|
||||
public BigDecimal getDistcountPrice() {
|
||||
// BigDecimal推荐使用String构造器,防止精度转换问题
|
||||
return super.getPrice().multiply(new BigDecimal("0.8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现打折价格逻辑
|
||||
* 根据里氏替换原则:父类实现的方法不应该覆盖
|
||||
* 获取原价
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public BigDecimal getPrice() {
|
||||
// BigDecimal推荐使用String构造器,防止精度转换问题
|
||||
return super.getPrice().multiply(new BigDecimal("0.8"));
|
||||
|
||||
return super.getPrice();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package top.fjy8018.designpattern.principle.liskovsubstitution.classdemo.before;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import top.fjy8018.designpattern.principle.liskovsubstitution.classdemo.after.ARectangle;
|
||||
import top.fjy8018.designpattern.principle.liskovsubstitution.classdemo.after.Quadrangle;
|
||||
|
||||
@Slf4j
|
||||
class SquareTest {
|
||||
|
||||
/**
|
||||
* resize要求传入父类对象,对长宽进行设置
|
||||
*
|
||||
* @param rectangle
|
||||
*/
|
||||
public static void resize(Rectangle rectangle) {
|
||||
while (rectangle.getWidth() <= rectangle.getLength()) {
|
||||
rectangle.setWidth(rectangle.getWidth() + 1);
|
||||
log.info("width:{} length:{}", rectangle.getWidth(), rectangle.getLength());
|
||||
if (rectangle.getWidth() > 50 || rectangle.getLength() > 50) {
|
||||
log.error("方法溢出");
|
||||
break;
|
||||
}
|
||||
}
|
||||
log.info("resize方法结束 width:{} length:{}", rectangle.getWidth(), rectangle.getLength());
|
||||
}
|
||||
|
||||
public static void resize(Quadrangle quadrangle) {
|
||||
while (quadrangle.getWidth() <= quadrangle.getLength()) {
|
||||
// quadrangle.setWidth(quadrangle.getWidth()+1);报错,原有方法已经不能正确运行,说明原有方法设计存在问题
|
||||
log.info("width:{} length:{}", quadrangle.getWidth(), quadrangle.getLength());
|
||||
if (quadrangle.getWidth() > 50 || quadrangle.getLength() > 50) {
|
||||
log.error("方法溢出");
|
||||
break;
|
||||
}
|
||||
}
|
||||
log.info("resize方法结束 width:{} length:{}", quadrangle.getWidth(), quadrangle.getLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
void before() {
|
||||
// 是长方形时业务正常运行
|
||||
Rectangle rectangle = new Rectangle();
|
||||
rectangle.setWidth(10);
|
||||
rectangle.setLength(20);
|
||||
resize(rectangle);
|
||||
// 使用之类替换父类对象,业务无法运行,方法溢出
|
||||
Square square = new Square();
|
||||
square.setLength(40);
|
||||
resize(square);
|
||||
}
|
||||
|
||||
@Test
|
||||
void after() {
|
||||
// 通过里氏替换原则改造后
|
||||
ARectangle aRectangle = new ARectangle();
|
||||
aRectangle.setLength(20);
|
||||
aRectangle.setWidth(10);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package top.fjy8018.designpattern.principle.liskovsubstitution.method.input.after;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
class ChildTest {
|
||||
|
||||
@Test
|
||||
void before() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void after() {
|
||||
Child child = new Child();
|
||||
// 此时希望调用子类重写的方法,若子类没重写,则应执行父类的方法
|
||||
child.method(new HashMap());
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,8 @@ class JavaCourseTest {
|
||||
Course course = new JavaDiscountCourse(1, "Java课程", new BigDecimal("99"));
|
||||
JavaDiscountCourse javaCourse = (JavaDiscountCourse) course;
|
||||
log.info("课程Id:{},课程名称:{},原价:{},折后价格:{}",
|
||||
javaCourse.getId(), javaCourse.getName(), javaCourse.getOriginPrice(),
|
||||
javaCourse.getPrice().setScale(2, BigDecimal.ROUND_HALF_UP));
|
||||
javaCourse.getId(), javaCourse.getName(), javaCourse.getPrice(),
|
||||
javaCourse.getDistcountPrice().setScale(2, BigDecimal.ROUND_HALF_UP));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user