diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/after/ARectangle.java b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/after/ARectangle.java new file mode 100644 index 0000000..858b437 --- /dev/null +++ b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/after/ARectangle.java @@ -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; + } +} diff --git a/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/after/ASquare.java b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/after/ASquare.java new file mode 100644 index 0000000..1f278ee --- /dev/null +++ b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/after/ASquare.java @@ -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; + } +} diff --git a/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/after/Quadrangle.java b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/after/Quadrangle.java new file mode 100644 index 0000000..0d864ab --- /dev/null +++ b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/after/Quadrangle.java @@ -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(); +} diff --git a/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/before/Rectangle.java b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/before/Rectangle.java new file mode 100644 index 0000000..bd40c37 --- /dev/null +++ b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/before/Rectangle.java @@ -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; + } +} diff --git a/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/before/Square.java b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/before/Square.java new file mode 100644 index 0000000..b3b1a02 --- /dev/null +++ b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/before/Square.java @@ -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; + } +} diff --git a/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/after/Base.java b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/after/Base.java new file mode 100644 index 0000000..aff5196 --- /dev/null +++ b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/after/Base.java @@ -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("父类被执行"); + } +} diff --git a/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/after/Child.java b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/after/Child.java new file mode 100644 index 0000000..9e3932f --- /dev/null +++ b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/after/Child.java @@ -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入参方法被执行"); + } + + +} diff --git a/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/before/Base.java b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/before/Base.java new file mode 100644 index 0000000..addef64 --- /dev/null +++ b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/before/Base.java @@ -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("父类被执行"); + } +} diff --git a/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/before/Child.java b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/before/Child.java new file mode 100644 index 0000000..ab3d982 --- /dev/null +++ b/src/main/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/before/Child.java @@ -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入参方法被执行"); + } + +} diff --git a/src/main/java/top/fjy8018/designpattern/principle/openclose/JavaDiscountCourse.java b/src/main/java/top/fjy8018/designpattern/principle/openclose/JavaDiscountCourse.java index d0b1f27..fef500e 100644 --- a/src/main/java/top/fjy8018/designpattern/principle/openclose/JavaDiscountCourse.java +++ b/src/main/java/top/fjy8018/designpattern/principle/openclose/JavaDiscountCourse.java @@ -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 diff --git a/src/test/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/before/SquareTest.java b/src/test/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/before/SquareTest.java new file mode 100644 index 0000000..f210840 --- /dev/null +++ b/src/test/java/top/fjy8018/designpattern/principle/liskovsubstitution/classdemo/before/SquareTest.java @@ -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); + + } +} \ No newline at end of file diff --git a/src/test/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/after/ChildTest.java b/src/test/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/after/ChildTest.java new file mode 100644 index 0000000..5dd9eea --- /dev/null +++ b/src/test/java/top/fjy8018/designpattern/principle/liskovsubstitution/method/input/after/ChildTest.java @@ -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()); + } +} \ No newline at end of file diff --git a/src/test/java/top/fjy8018/designpattern/principle/openclose/JavaCourseTest.java b/src/test/java/top/fjy8018/designpattern/principle/openclose/JavaCourseTest.java index 844caa5..337e92a 100644 --- a/src/test/java/top/fjy8018/designpattern/principle/openclose/JavaCourseTest.java +++ b/src/test/java/top/fjy8018/designpattern/principle/openclose/JavaCourseTest.java @@ -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)); } } \ No newline at end of file