110.【十万字带你深入学习23种设计模式】(二)

简介: 110.【十万字带你深入学习23种设计模式】
(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处理器");
    }
}
相关文章
|
3月前
|
设计模式 监控 安全
多线程设计模式【多线程上下文设计模式、Guarded Suspension 设计模式、 Latch 设计模式】(二)-全面详解(学习总结---从入门到深化)
多线程设计模式【多线程上下文设计模式、Guarded Suspension 设计模式、 Latch 设计模式】(二)-全面详解(学习总结---从入门到深化)
84 0
|
2月前
|
设计模式 存储 算法
设计模式学习心得之五种创建者模式(2)
设计模式学习心得之五种创建者模式(2)
22 2
|
2月前
|
设计模式 uml
设计模式学习心得之前置知识 UML图看法与六大原则(下)
设计模式学习心得之前置知识 UML图看法与六大原则(下)
18 2
|
2月前
|
设计模式 安全 Java
设计模式学习心得之五种创建者模式(1)
设计模式学习心得之五种创建者模式(1)
19 0
|
2月前
|
设计模式 数据可视化 程序员
设计模式学习心得之前置知识 UML图看法与六大原则(上)
设计模式学习心得之前置知识 UML图看法与六大原则(上)
18 0
|
3月前
|
设计模式 安全 Java
【JAVA学习之路 | 基础篇】单例设计模式
【JAVA学习之路 | 基础篇】单例设计模式
|
3月前
|
设计模式 安全 Java
【设计模式学习】单例模式和工厂模式
【设计模式学习】单例模式和工厂模式
|
3月前
|
设计模式 算法 程序员
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
|
3月前
|
设计模式 存储 前端开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
|
3月前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式