里氏替换原则原则

This commit is contained in:
2018-09-23 13:10:21 +08:00
parent 1433dabd23
commit 7b18f0dcf0
14 changed files with 437 additions and 8 deletions

124
.idea/uiDesigner.xml generated Normal file
View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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("父类被执行");
}
}

View File

@@ -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入参方法被执行");
}
}

View File

@@ -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("父类被执行");
}
}

View File

@@ -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入参方法被执行");
}
}

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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());
}
}

View File

@@ -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));
}
}