里氏替换原则原则
This commit is contained in:
124
.idea/uiDesigner.xml
generated
Normal file
124
.idea/uiDesigner.xml
generated
Normal 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>
|
||||
@@ -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