设计模式-六大原则

news2025/1/16 16:12:27

设计模式的六大原则是软件工程中的基本概念,使得构建可维护、可扩展和可重用的代码。
1.单一职责原则(Single Responsibility Principle):一个类或方法应该只有一个引起变化的原因,确保类或模块的功能高度内聚。
案例:

public class Affair {
    public void study(String animal){
        System.out.println(animal+"学习了");
    }
}
public class Client {
    public static void main(String[] args) {
      Affair affair=new Affair();
      affair.study("张三");
    }
}

遵循单一职责原则的优点有:
1.可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;
2.提高类的可读性,提高系统的可维护性;
3.变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。

2.开闭原则(Open-Closed Principle):软件实体(如类、模块等)应对扩展开放,对修改封闭。这意味着系统可以轻易地增加新功能而不需要修改已有的代码。

3.里氏替换原则(Liskov Substitution Principle):子类应该能够替换其基类,而不会改变程序的正确性。这保证了继承体系中的类型安全。
里氏替换原则:子类可以扩展父类的功能,但不能改变父类原有的功能。
1.子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
2.子类中可以增加自己特有的方法。
3.当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
4.当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
案例:

public class Student {
    public double grossScore(double m,double n){
        return m+n;
    }
}

public class Student1 extends Student{
    public double grossScore(double m,double n){
        return m+n;
    }

    public double average(double m,double n){
        return (m+n)/2;
    }
}
public class Client {
    public static void main(String[] args) {
        Student student=new Student();
        System.out.println("学生总分数为:"+student.grossScore(98.3, 81.3));

        Student1 student1=new Student1();
        System.out.println("学生平均分数为:"+student1.average(98.3, 81.3));
    }
}

4.依赖倒置原则(Dependency Inversion Principle):高层模块不应直接依赖于低层模块,而是都应该依赖于抽象。抽象不应该依赖细节,细节应该依赖抽象。这有助于减少代码之间的耦合,提高系统的可维护性。

public interface Campaign {
    String getMovement();
}

public class Exercise {
    public void motion(Campaign campaign){
        System.out.println("开始运动了");
        System.out.println(campaign.getMovement());
    }
}
public class BasketBall implements Campaign{

    @Override
    public String getMovement() {
        return "打篮球咯!!!";
    }
}

public class Football implements Campaign{
    @Override
    public String getMovement() {
        return "踢足球了咯!!!";
    }
}
public class Client {
    public static void main(String[] args) {
        Exercise exercise=new Exercise();
        exercise.motion(new BasketBall());
        exercise.motion(new Football());
    }
}

在这里插入图片描述
5.接口隔离原则(Interface Segregation Principle):客户端不应被要求依赖它们不需要的接口。这有助于减少类对接口的依赖,提高系统的灵活性和可重用性。
反例,代码臃肿:

//接口
public interface ConnectorsA {
    void methodA();
    void methodB();
    void methodC();
    void methodD();
    void methodE();
}
//调用
public class BasicsA {
    public void dependA(ConnectorsA connectorsA){
        connectorsA.methodA();
    }
    public void dependB(ConnectorsA connectorsA){
        connectorsA.methodB();
    }
    public void dependC(ConnectorsA connectorsA){
        connectorsA.methodC();
    }
}
//接口实现
public class BasicsADepend implements ConnectorsA {

    @Override
    public void methodA() {
        System.out.println("类BasicsDepend实现接口ConnectorsA的方法A");
    }

    @Override
    public void methodB() {
        System.out.println("类BasicsDepend实现接口ConnectorsA的方法B");
    }

    @Override
    public void methodC() {
        System.out.println("类BasicsDepend实现接口ConnectorsA的方法C");
    }

    @Override
    public void methodD() {
    }

    @Override
    public void methodE() {
    }
}
//调用
public class BasicsB {
    public void dependA(ConnectorsA connectorsA){
        connectorsA.methodA();
    }
    public void dependB(ConnectorsA connectorsA){
        connectorsA.methodD();
    }
    public void dependC(ConnectorsA connectorsA){
        connectorsA.methodE();
    }
}
//接口实现
public class BasicsBDepend implements ConnectorsA {
    @Override
    public void methodA() {
        System.out.println("类BasicsBDepend实现接口ConnectorsA的方法A");
    }
    @Override
    public void methodB() {

    }
    @Override
    public void methodC() {

    }
    @Override
    public void methodD() {
        System.out.println("类BasicsBDepend实现接口ConnectorsA的方法D");
    }
    @Override
    public void methodE() {
        System.out.println("类BasicsBDepend实现接口ConnectorsA的方法E");
    }
}
//Test
public class Client {
    public static void main(String[] args) {
        BasicsA basicsA=new BasicsA();
        basicsA.dependA(new BasicsADepend());
        basicsA.dependB(new BasicsADepend());
        basicsA.dependC(new BasicsADepend());

        BasicsB basicsB=new BasicsB();
        basicsB.dependA(new BasicsBDepend());
        basicsB.dependB(new BasicsBDepend());
        basicsB.dependC(new BasicsBDepend());
    }
}

使得接口分离优化为正例:

//接口拆分
public interface ConnectorsA1 {
    void methodA();
}
//接口拆分
public interface ConnectorsA2 {
    void methodB();
    void methodC();
}
//接口拆分
public interface ConnectorsA3 {
    void methodD();
    void methodE();
}
//调用
public class BasicsA {
    public void dependA(ConnectorsA1 connectorsA1){
        connectorsA1.methodA();
    }
    public void dependB(ConnectorsA2 connectorsA2){
        connectorsA2.methodB();
    }
    public void dependC(ConnectorsA2 connectorsA2){
        connectorsA2.methodC();
    }
}
//接口实现
public class BasicsADepend implements ConnectorsA1,ConnectorsA2 {

    @Override
    public void methodA() {
        System.out.println("类BasicsDepend实现接口ConnectorsA1的方法A");
    }
    @Override
    public void methodB() {
        System.out.println("类BasicsDepend实现接口ConnectorsA2的方法B");
    }
    @Override
    public void methodC() {
        System.out.println("类BasicsDepend实现接口ConnectorsA2的方法C");
    }
}
//调用
public class BasicsB {
    public void dependA(ConnectorsA1 connectorsA1){
        connectorsA1.methodA();
    }
    public void dependB(ConnectorsA3 connectorsA1){
        connectorsA1.methodD();
    }
    public void dependC(ConnectorsA3 connectorsA3){
        connectorsA3.methodE();
    }
}
//接口实现
public class BasicsBDepend implements ConnectorsA1,ConnectorsA3 {
    @Override
    public void methodA() {
        System.out.println("类BasicsBDepend实现接口ConnectorsA1的方法A");
    }
    @Override
    public void methodD() {
        System.out.println("类BasicsBDepend实现接口ConnectorsA3的方法D");
    }
    @Override
    public void methodE() {
        System.out.println("类BasicsBDepend实现接口ConnectorsA3的方法E");
    }
}
//Test
public class Client {
    public static void main(String[] args) {
        BasicsA basicsA=new BasicsA();
        basicsA.dependA(new BasicsADepend());
        basicsA.dependB(new BasicsADepend());
        basicsA.dependC(new BasicsADepend());

        BasicsB basicsB=new BasicsB();
        basicsB.dependA(new BasicsBDepend());
        basicsB.dependB(new BasicsBDepend());
        basicsB.dependC(new BasicsBDepend());
    }
}

采用接口隔离原则对接口进行约束时,要注意
1.接口尽量小,要适度。对接口进行细化,提高程序设计灵活性。过小,则会造成接口数量过多,使设计复杂化,即要适度。
2.为依赖接口的类定制服务,只暴露给调用的类它需要的方法,不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。
3.提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。

6.迪米特法则(Law of Demeter):一个对象应对其他对象有最少的了解。这有助于降低类之间的耦合度,提高系统的稳定性和可维护性。
反例:一集团公司,下属单位有分公司和直属部门,现在要求打印出所有下属单位的员工ID。

//总公司
public class Employee {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}
//分公司
public class SubEmployee {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}
//分公司ID管理
public class SubCompanyManager {
    public List<SubEmployee> getAllEmployeee(){
        List<SubEmployee> list = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            SubEmployee employee = new SubEmployee();
            employee.setId("分公司"+i);
            list.add(employee);
        }
        return list;
    }
}
//总公司ID管理
public class CompanyManager {
    public List<Employee> getAllWmployee(){
        ArrayList<Employee> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Employee employee = new Employee();
            employee.setId("总公司"+i);
            list.add(employee);
        }
        return list;
    }

    public void printAllEmployee(SubCompanyManager subCM){
        List<SubEmployee> allEmployeee = subCM.getAllEmployeee();
        for (SubEmployee subEmployee : allEmployeee) {
            System.out.print(subEmployee.getId()+" ");
        }
        System.out.println();
        System.out.println("------------------------------------------------------------");
        List<Employee> allWmployee = this.getAllWmployee();
        for (Employee employee : allWmployee) {
            System.out.print(employee.getId()+" ");
        }
    }
}
//Test
public class Client {
    public static void main(String[] args) {
        CompanyManager companyManager = new CompanyManager();
        companyManager.printAllEmployee(new SubCompanyManager());
    }
}

优化CompanyManager后

public class SubCompanyManager {
    public List<SubEmployee> getAllEmployeee(){
        List<SubEmployee> list = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            SubEmployee employee = new SubEmployee();
            employee.setId("分公司"+i);
            list.add(employee);
        }
        return list;
    }
    public void printEmployee(){
        List<SubEmployee> list = this.getAllEmployeee();
        for (SubEmployee subEmployee : list) {
            System.out.print(subEmployee.getId());
        }
    }
}

public class CompanyManager {
    public List<Employee> getAllWmployee(){
        ArrayList<Employee> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Employee employee = new Employee();
            employee.setId("总公司"+i);
            list.add(employee);
        }
        return list;
    }

    public void printAllEmployee(SubCompanyManager subCM){
        subCM.printEmployee();
        System.out.println();
        System.out.println("------------------------------------------------------------");
        List<Employee> allWmployee = this.getAllWmployee();
        for (Employee employee : allWmployee) {
            System.out.print(employee.getId()+" ");
        }
    }
}

优化后:达到解耦

转自:https://www.cnblogs.com/bruce1992/p/15096265.html
学习分享输出是一种对大脑的刺激

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1623051.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣数据库题库学习(4.22日)

577. 员工奖金 问题链接 思路分析 Employee表与Bonus表通过empId字段可以连接&#xff0c;需求是查出奖金少于1000的员工名和奖金值。 这里奖金少于1000的情况就是没有奖金有奖金但少于1000 这里我给出的解决方案就是使用左连接&#xff0c;将Employee表作为左表&#xff…

c++二叉树的进阶--二叉搜索树

1. 二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值 它的左…

企业为什么要选择通配符SSL证书使用?

企业选择使用通配符SSL证书主要是出于以下几个重要原因&#xff1a; 1. 经济性&#xff1a; - 节省成本&#xff1a;相较于为每一个子域名单独购买并维护单独的SSL证书&#xff0c;通配符证书能够以一张证书覆盖同一主域名下的所有同级子域名&#xff0c;无需为新增或已有的子域…

SpringBoot框架——8.MybatisPlus常见用法(常用注解+内置方法+分页查询)

1.MybatisPlus常用注解&#xff1a; 1.1 当数据库、表名和字段名和实体类完全一致时无需加注解&#xff0c;不一致时&#xff1a; TableName指定库名 TableId指定表名 TableField指定字段名 1.2 自增主键&#xff1a; TableId(typeIdType.AUTO) private Long id; 1.3 实体类中属…

【JAVA】java 中的Stream 常用函数

java 中的Stream 常用函数 一、简介1.1、什么是Stream&#xff1f;1.2、创建Stream1.3、Stream的特性 二、Stream的操作2.1、中间操作&#xff1a;2.2、终端操作&#xff1a;2.3、Stream的并行处理 三、Stream 常用函数四、使用示例4.1、计算集合中偶数的平方和&#xff1a;4.2…

新手也能学会的甘特图制作教程

甘特图是什么&#xff1f; 甘特图(Gantt Chart)是一种以图表形式直观展示项目计划的工具,由20世纪初的管理学家亨利甘特(Henry Gantt)发明并命名。它具有以下几个主要特点: 水平时间轴 甘特图的横轴是一条时间轴,通常按天、周或月来刻度,直观展示了项目从开始到结束的整个时间…

【信息收集】端口扫描masscan负载均衡识别lbd

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将信息做其他用途&#xff0c;由Ta承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 1、什么是masscan masscan在kali系统上是自带的端口扫描…

回归预测 | Matlab实现BO-RF贝叶斯优化随机森林多变量回归预测

回归预测 | Matlab实现BO-RF贝叶斯优化随机森林多变量回归预测 目录 回归预测 | Matlab实现BO-RF贝叶斯优化随机森林多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现BO-RF贝叶斯优化随机森林多变量回归预测&#xff1b; 2.输入7个特征&#xf…

考研日常记录(upd 24.4.24)

由于实在太无聊了 &#xff0c; 所以记录以下考研备考日常 &#xff0c; 增加一点成就感 &#xff0c; 获得一点前进动力。 文章目录 2024.4.18 周四课程情况&#xff1a;时间规划&#xff1a; 2024.4.19 周五课程情况&#xff1a;时间规划&#xff1a; 2024.4.20 周六2024.4.2…

Java知识总结---并发篇

线程 线程的状态 Java中线程可以有如下6中状态&#xff1a; NEW 新创建 RUNNABLE 可运行 BLOCKED 阻塞 WAITING 等待 TIMED WAITING 计时等待 TERMINATED 终止 线程的创建 &#xff08;1&#xff09;继承Thread类 public class ExtendsThread extends Thread { O…

学习Docker笔记

在23号刚刚学完新版本的docker还想说回去继续学习老版本的springcloud课程里面的docker 结果一看黑马首页新版本课程出了&#xff0c;绷不住了。以下是我学习新版本docker的笔记&#xff0c;记录了我学习过程遇到的各种bug和解决&#xff0c;也参考了黑马老师的笔记&#xff1a…

SLMs之Phi-3:Phi-3的简介、安装和使用方法、案例应用之详细攻略

SLMs之Phi-3&#xff1a;Phi-3的简介、安装和使用方法、案例应用之详细攻略 导读&#xff1a;2024年4月23日&#xff0c;微软发布Phi-3&#xff0c;这是微软推出的一款新的开源AI模型家族Phi-3。背景痛点&#xff1a;小语言模型(SLM)尽管规模不大&#xff0c;但在语言理解、代码…

three.js 制作卡牌正反面 旋转

1.效果图 2.代码 <template><div><div id"container"></div></div> </template><script> import * as THREE from "three"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.…

C语言指针进阶:各类型指针变量详解

目录 1. 字符指针变量2. 数组指针变量2.1 什么是数组指针变量2.2 数组指针变量的初始化 3. 二维数组传参的本质4. 函数指针变量4.1 函数指针变量的创建4.2 函数指针变量的使用4.3 代码分析4.3.1 typedef 关键字 5. 函数指针数组6. 转移表 正文开始。 1. 字符指针变量 我们可以…

融合算法:引力融合

问题&#xff1a; 有一批数据&#xff0c;如&#xff1a; [ 1, 2, 3, 45, 46, 55, 89, 101 ]想把它分成3块&#xff0c;如&#xff1a; [1, 2, 3] [45, 46, 55] [89, 101]算法&#xff1a; 参考万有引力公式&#xff0c;想象坐标轴上这8个点的分布&#xff1a; 每一个点都会…

偏执型人格的症状和起因,偏执型人格测试和应对方法

偏执型人格&#xff0c;主打一个敏感多疑&#xff0c;过分的固执&#xff0c;过度的警觉。无论别人怎么解析&#xff0c;都难以说服。偏执型人格常常毫无根据的怀疑他人的忠诚&#xff08;动机&#xff09;&#xff0c;曲解别人的言语&#xff08;或行为&#xff09;&#xff0…

MySQL--表的操作

目录 创建表 查看表结构 修改表 新增列 修改列类型 修改列名 修改表名&#xff1a; 删除列 删除表 创建表 语法&#xff1a; CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引…

数据结构 - 顺序表

一. 线性表的概念 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续的…

分类算法——决策树(五)

认识决策树 决策树思想的来源非常朴素&#xff0c;程序设计中的条件分支结构就是if-else结构&#xff0c;最早的决策树就是利用这类结构分割数据的一种分类学习方法。 决策树分类原理详解 为了更好理解决策树具体怎么分类的&#xff0c;通过一个问题例子&#xff1a; 问题…

每日OJ题_BFS解决拓扑排序③_力扣LCR 114. 火星词典

目录 力扣LCR 114. 火星词典 解析代码 力扣LCR 114. 火星词典 LCR 114. 火星词典 难度 困难 现有一种使用英语字母的外星文语言&#xff0c;这门语言的字母顺序与英语顺序不同。 给定一个字符串列表 words &#xff0c;作为这门语言的词典&#xff0c;words 中的字符串已…