(2).里氏代换原则 (添加不重写)
里氏代换原则是面向对象设计的基本原则之一。
里氏代换原则: 任何基类可以出现的地方,子类一定可以出现
。通俗的理解: 子类可以扩展父类的功能,但不能改变原有的功能。换句话说,子类继承父类时,除了**添加新的方法完成新增功能外,尽量不要重写父类的方法**。
如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的概率非常大。
经典列子:
eg: 正方形不是长方形
在数学领域里,正方形为一体是长方形,他是一个长度相等的长方形。所以,我们开发的一个与集合图形相关的软件系统,就可以顺利成章的让正方形继承自长方形。
反列
长方形类
package com.jsxs.principles.demo2; /** * @Author Jsxs * @Date 2023/4/15 21:35 * @PackageName:com.jsxs.principles.demo2 * @ClassName: Rectangle * @Description: TODO 长方形 * @Version 1.0 */ public class Rectangle { private double length; private double width; public double getLength() { return length; } public void setLength(double length) { this.length = length; } public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } }
正方形类
package com.jsxs.principles.demo2; /** * @Author Jsxs * @Date 2023/4/15 21:36 * @PackageName:com.jsxs.principles.demo2 * @ClassName: Square * @Description: TODO 正方形: “继承长方形” * @Version 1.0 */ public class Square extends Rectangle{ //1. 继承长方形 @Override public void setLength(double length) { //2.重写长方形的长 super.setLength(length); super.setWidth(length); } @Override public void setWidth(double width) { // 3.重写长方形的宽 super.setWidth(width); super.setLength(width); } }
测试类
package com.jsxs.principles.demo2; /** * @Author Jsxs * @Date 2023/4/15 21:40 * @PackageName:com.jsxs.principles.demo2 * @ClassName: RectangleTest * @Description: TODO * @Version 1.0 */ public class RectangleTest { public static void main(String[] args) { Rectangle rectangle = new Rectangle(); rectangle.setWidth(10); rectangle.setLength(20); // 进行扩宽的操作 resize(rectangle); printLengthAndWidth(rectangle); // 尝试传递子类而不是不基类 System.out.println("---------------------"); Square square = new Square(); square.setLength(10); square.setWidth(10); resize(square); printLengthAndWidth(square); } // 扩展方法 public static void resize(Rectangle rectangle){ // 判断宽如果比长小,那么就进行扩宽的操作 while (rectangle.getWidth()<=rectangle.getLength()){ rectangle.setWidth(rectangle.getWidth()+1); } } // 打印长和宽 public static void printLengthAndWidth(Rectangle rectangle){ System.out.println(rectangle.getWidth()); System.out.println(rectangle.getLength()); } }
我们运行这段代码就会发现:“假如是长方形传入,那么就会输出长和宽,但是当我们正方形传入,我们就会发现程序会一直处于循环状态,并不会输出任何的日志信息。得出结论:“长方形适合这个代码、正方形不适合这个代码。基类能出现的地方,子类一定可以出现,假如基类能出现的地方,子类不能出现,那么就违反了里氏代换原则。””
正列
接口
package com.jsxs.principles.demo2.after; /** * @Author Jsxs * @Date 2023/4/16 7:52 * @PackageName:com.jsxs.principles.demo2.after * @ClassName: Quadrilateral * @Description: TODO 四边形接口 * @Version 1.0 */ public interface Quadrilateral { double getLength(); //获取长 double getWidth(); //获取宽 }
长方形
package com.jsxs.principles.demo2.after; /** * @Author Jsxs * @Date 2023/4/16 7:55 * @PackageName:com.jsxs.principles.demo2.after * @ClassName: Rectangle * @Description: TODO 长方形实现接口 * @Version 1.0 */ public class Rectangle implements Quadrilateral{ private double length; private double width; @Override public double getLength() { return length; } @Override public double getWidth() { return width; } public void setLength(double length) { this.length = length; } public void setWidth(double width) { this.width = width; } }
正方形
package com.jsxs.principles.demo2.after; /** * @Author Jsxs * @Date 2023/4/16 7:53 * @PackageName:com.jsxs.principles.demo2.after * @ClassName: Square * @Description: TODO 正方形实现四边形的接口 * @Version 1.0 */ public class Square implements Quadrilateral{ private double side; //1.定义变量边长 @Override public double getLength() { return side; } @Override public double getWidth() { return side; } public void setSide(double side) { this.side = side; } }
测试实现类
package com.jsxs.principles.demo2.after; /** * @Author Jsxs * @Date 2023/4/16 7:56 * @PackageName:com.jsxs.principles.demo2.after * @ClassName: RectangleTest * @Description: TODO * @Version 1.0 */ public class RectangleTest { public static void main(String[] args) { // 1. 创建长方形的对象 com.jsxs.principles.demo2.after.Rectangle rectangle = new com.jsxs.principles.demo2.after.Rectangle(); // 创建一个对象 rectangle.setLength(20); rectangle.setWidth(10); // 2.调用方法进行扩宽的操作 resize(rectangle); printLengthAndWidth(rectangle); } // 扩展方法 public static void resize(Rectangle rectangle){ // 这个参数是: after的。这里我们传入的是长方形,因为长方形和正方形没有了父子关系,所以这里只能进行传输正正方形。 // 判断宽如果比长小,那么就进行扩宽的操作 while (rectangle.getWidth()<=rectangle.getLength()){ rectangle.setWidth(rectangle.getWidth()+1); } } // 打印长和宽 public static void printLengthAndWidth(Quadrilateral quadrilateral){ System.out.println(quadrilateral.getWidth()); System.out.println(quadrilateral.getLength()); } }
(3).依赖倒转原则 (找接口不找具体类)
高层模块不应该依赖底层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。简单地说: 就是要求对抽象进行编程,不要对实现进行编程
,这样就降低了客户与实现魔窟啊的耦合。
高层模块不应该依赖于底层模块
细节应该依赖于抽象
eg: 组装电脑
现要组装一台电脑,需要陪考吗CPU、硬盘、内存条。只有这些配置都有了,计算机次啊能正常的运行。选择CPU有很多选择,如Inter、AMD等,硬盘可以选择希捷,西数等,内存条可以选择金士顿、海盗船等。
组合关系
硬盘
package com.jsxs.principles.demo3.before; /** * @Author Jsxs * @Date 2023/4/16 8:54 * @PackageName:com.jsxs.principles.demo3.before * @ClassName: yingpan * @Description: TODO 硬盘 * @Version 1.0 */ public class yingpan { // 1.存储数据的方法 public void save(String date){ System.out.println("硬盘存储数据: "+date); } // 2.获取数据的方法 public String get(){ System.out.println("获取硬盘存储数据: "); return "数据"; } }
处理器
package com.jsxs.principles.demo3.before; /** * @Author Jsxs * @Date 2023/4/16 8:56 * @PackageName:com.jsxs.principles.demo3.before * @ClassName: CPU * @Description: TODO CPU中央处理器 * @Version 1.0 */ public class CPU { public void run(){ System.out.println("使用CPU处理器"); } }