Java进阶--面向对象设计原则
设计模式
概念
设计模式,又称软件设计模式,是一套被反复使用,经过分类编目的,代码设计经验的总结。描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方。它是解决特定问题的一系列套路,是前辈们代码设计经验的总结,具有一定普遍性,可以反复使用。
优点
设计模式的本质是面型对象设计原则的实际运用,是对类的封装性,继承性和多态性以及类的关联关系和组合关系的充分理解。
正确使用设计模式具有的优点:
可以提高程序员的思维能力,编程能力,和设计能力。
使程序设计更加规范,提高开发效率。
使设计的代码可重用性高,可读性强,可靠性高,灵活性好,可维护性强。
能够更好地理解源码架构。
面向对象设计原则
在面向对象的设计过程中,首先要考虑的是如何提高软件系统的可维护性与可复用性。
单一职责原则
单一职责原则,可以理解为一个类只负责一个功能领域的职责,不要什么都写在一个类中,否则导致类变得“杂乱”,耦合度过高,不利于扩展。
以项目开发为例,如果项目组成员每个人的职责都很明确,可以专心开发自 己负责的模块,则项目成果的质量往往很高。相反,如果职责不清晰,分工就会混乱。
开闭原则
开闭原则即对扩展开放,对修改封闭。程序扩展时,不建议修改原有代码,建议通过扩展一个新的类(方法)来实现新的功能。
以汽车工厂生产汽车举例:
反例(不使用开闭原则):
public class CarDemo {public static void main(String[] args) {//现在需要生产汽车new CarFactory().createCar(1);new CarFactory().createCar(2);new CarFactory().createCar(3);//扩展新品牌汽车业务}}class CarFactory{public void createCar(int type){if(type==1){System.out.println("生产宝马汽车"+new Car("宝马汽车"));}else if(type==2){System.out.println("生产奥迪汽车"+new Car("奥迪汽车"));}else if(type==3){System.out.println("生产大众汽车"+new Car("大众汽车"));}//如果需要生产新品牌的汽车,就需要再次修改代码}}class Car{String name;public Car(String name) {this.name = name;}
}
正例(使用开闭原则):
直接创建一个汽车类作为基类,不同品牌汽车继承此基类,当需要扩展新品牌的业务时,只需要扩展一个新的汽车类继承汽车基类并重写生产方法,再使用汽车工厂去调用子类方法即可,就不会修改原有代码,提高代码的可复用性与可维护性。
class CarDemo{public static void main(String[] args) {new CarFactory().carfactory(new BMW());new CarFactory().carfactory(new Aodi());new CarFactory().carfactory(new DaZhong());new CarFactory().carfactory(new BenChi());}}class CarFactory{void carfactory(Car car){car.createCar();}
}abstract class Car{public abstract void createCar();
}class BMW extends Car{@Overridepublic void createCar() {System.out.println("生产宝马汽车");}
}class Aodi extends Car{@Overridepublic void createCar() {System.out.println("生产奥迪汽车");}
}class DaZhong extends Car{@Overridepublic void createCar() {System.out.println("生产大众汽车");}
}class BenChi extends Car{@Overridepublic void createCar() {System.out.println("生产奔驰汽车");}
}
里氏替换原则
所有使用父类的地方必须能透明地使用其子类的对象。
里氏替换原则表明,在软件中将一个基类对象替换成它的子类对象时程序将 不会产生任何错误和异常。
任何基类可以出现的地 方,子类一定可以出现。所以,子类可以扩展父类的功能,但不能改变父类原有的功能。换句话说,子类继承父类时除添加新的方法完成新增功能外尽量不要重写父类的方法。
其核心思想是:子类对象必须能够替换父类对象,且替换后程序的行为不变。这意味着继承关系应确保子类在不改变父类原有功能的前提下进行扩展,而非修改。
反例:
父类:Rectangle
(矩形)
子类:Square
(正方形)
class Rectangle {protected int width;protected int height;public void setWidth(int width) {this.width = width;}public void setHeight(int height) {this.height = height;}public int getArea() {return width * height;}
}class Square extends Rectangle {// 正方形要求宽高相等,强制重写set方法@Overridepublic void setWidth(int width) {super.setWidth(width);super.setHeight(width); // 修改父类行为}@Overridepublic void setHeight(int height) {super.setHeight(height);super.setWidth(height); // 修改父类行为}
}
问题:
-
Square
重写setWidth
和setHeight
,改变父类行为。 -
当
Rectangle
被Square
替换时,预期面积计算逻辑可能出错。
修正:
// 抽象基类定义公共行为
abstract class Shape {public abstract int getArea();
}class Rectangle extends Shape {private int width;private int height;public void setWidth(int width) {this.width = width;}public void setHeight(int height) {this.height = height;}@Overridepublic int getArea() {return width * height;}
}class Square extends Shape {private int side;public void setSide(int side) {this.side = side;}@Overridepublic int getArea() {return side * side;}
}
使用Shape的时候可以透明替换成Rectangle
和Square。
小结:里氏替换原则强调子类对父类的透明替换,是保证多态性和继承合理性的基石。通过设计一致的接口、约束子类行为,可提升代码的健壮性和可维护性。在实践中,若发现子类需要颠覆父类逻辑,往往是设计缺陷的信号,需及时重构。
依赖倒置原则
上层模块不应该依赖底层模块,它们都应该依赖于抽象.
抽象不应该依赖于细节,细节应该依赖于抽象.
如果有多个同类型事物时,我们可以抽取一个共同抽象层,具体的实现细节应该依赖于抽象.
反例:订单服务直接依赖 MySQL 数据库操作。
// 低层模块:MySQL 数据库操作
class MySQLDatabase {public void saveOrder(String orderData) {System.out.println("保存订单到 MySQL: " + orderData);}
}// 高层模块:订单处理服务
class OrderService {private MySQLDatabase database = new MySQLDatabase(); // ❌ 直接依赖具体实现public void processOrder(String order) {database.saveOrder(order);}
}
程序要依赖于抽象接口,不要依赖于具体实现。
-
若需切换数据库(如改为 MongoDB),需修改
OrderService
代码,违反开闭原则。 -
高层模块与低层模块紧耦合,难以独立测试或扩展。
修正:
interface DatabaseService {void save(String data);
}
//低层模块实现接口
class MySQLDatabase implements DatabaseService {@Overridepublic void save(String data) {System.out.println("保存到 MySQL: " + data);}
}class MongoDBDatabase implements DatabaseService {@Overridepublic void save(String data) {System.out.println("保存到 MongoDB: " + data);}
}
//高层模块依赖抽象
class OrderService {private DatabaseService database; // ✅ 依赖抽象接口// 通过构造函数注入依赖(依赖注入)public OrderService(DatabaseService database) {this.database = database;}public void processOrder(String order) {database.save(order);}
}
接口隔离原则
客户端不应被迫依赖它们不使用的接口。通过定义细粒度的接口,减少类之间的耦合,避免“胖接口”导致的冗余实现和潜在风险。
反例:设计一个多功能设备接口,涵盖打印、扫描和传真功能
// ❌ 违反 ISP:臃肿接口,强制所有实现类支持所有方法
interface MultiFunctionDevice {void print(String document);void scan(String document);void fax(String document);
}// 普通打印机只能打印,但被迫实现空方法
class BasicPrinter implements MultiFunctionDevice {@Overridepublic void print(String document) {System.out.println("打印文档: " + document);}@Overridepublic void scan(String document) {// 不支持扫描,空实现(可能引发逻辑错误)throw new UnsupportedOperationException("不支持扫描");}@Overridepublic void fax(String document) {// 不支持传真,空实现throw new UnsupportedOperationException("不支持传真");}
}
问题:
-
冗余代码:
BasicPrinter
被迫实现无用的方法(如scan()
和fax()
)。 -
脆弱性:接口变更(如新增方法)会强制所有实现类修改,违反开闭原则。
-
误导性:接口声明支持扫描和传真,但实际实现可能抛出异常。
修正:
1.拆分接口
// ✅ 拆分后的接口
interface Printer {void print(String document);
}interface Scanner {void scan(String document);
}interface FaxMachine {void fax(String document);
}
2.按需实现接口
// 基础打印机仅实现打印功能
class BasicPrinter implements Printer {@Overridepublic void print(String document) {System.out.println("打印文档: " + document);}
}// 高级设备组合多个功能
class AdvancedMultiFunctionDevice implements Printer, Scanner, FaxMachine {@Overridepublic void print(String document) {System.out.println("高级打印: " + document);}@Overridepublic void scan(String document) {System.out.println("扫描文档: " + document);}@Overridepublic void fax(String document) {System.out.println("发送传真: " + document);}
}
3.按需使用接口
public class Office {// 仅依赖打印机接口public void printReport(Printer printer, String report) {printer.print(report);}// 依赖扫描和打印接口public void copyDocument(Printer printer, Scanner scanner, String doc) {scanner.scan(doc);printer.print(doc);}
}
小结:接口隔离原则通过 细化接口职责 和 最小化依赖,有效提升系统的灵活性和可维护性。
迪米特原则
又称最少知识原则,其核心是降低类之间的耦合度,通过限制对象间的交互范围,确保每个模块(类)只需了解与其直接相关的组件,从而提高系统的灵活性和可维护性。
核心规则
一个对象应仅与以下“直接朋友”交互:
-
自身成员变量
-
方法参数
-
方法内部创建的对象
-
当前对象的直接组件(如集合中的元素)
禁止行为:
-
链式调用:如
a.getB().getC().doSomething()
(通过中间对象访问间接依赖)。 -
直接操作陌生对象:避免直接调用非直接朋友的方法或访问其属性。
反例:
class Employee {private DepartmentManager manager;public void getCeoContact() {// ❌ 链式调用:employee -> manager -> ceoString ceoPhone = manager.getCeo().getPhone();System.out.println("CEO联系方式: " + ceoPhone);}
}class DepartmentManager {private CEO ceo;public CEO getCeo() {return ceo;}
}class CEO {private String phone;public String getPhone() {return phone;}
}
问题:
-
Employee
类通过DepartmentManager
间接依赖CEO
,形成耦合链。 -
若
CEO
的联系方式获取逻辑变更(如改为邮箱),需修改所有链式调用处。
修正:
class Employee {private DepartmentManager manager;public void getCeoContact() {// ✅ 仅与直接朋友(manager)交互,不感知CEO的存在String ceoContact = manager.getCeoContact();System.out.println("CEO联系方式: " + ceoContact);}
}class DepartmentManager {private CEO ceo;public String getCeoContact() {// 封装与CEO的交互细节return ceo.getContactInfo();}
}class CEO {private String phone;public String getContactInfo() {return phone;// 若逻辑变更,只需修改此处(如 return email;)}
}
-
隐藏细节:
DepartmentManager
封装与CEO
的交互,避免Employee
直接依赖底层类。 -
降低耦合:
CEO
的修改仅影响DepartmentManager
,无需改动Employee
优势 | 说明 |
---|---|
降低耦合度 | 模块间依赖关系简化,减少连锁修改风险。 |
提高可维护性 | 封装交互细节,逻辑变更影响范围可控。 |
增强封装性 | 对象内部结构对客户端隐藏,避免外部直接操作私有状态。 |
减少风险扩散 | 局部故障不易扩散至整个系统。 |
小结:迪米特原则通过限制对象间的交互范围,推动系统向高内聚、低耦合的方向演进。
组合/聚合复用原则
关系类型 | 定义 | 生命周期管理 | 示例 |
---|---|---|---|
组合 | 强关联,整体与部分不可分割,部分不能独立于整体存在。 | 整体负责部分的创建与销毁。 | 汽车 与 发动机 (汽车销毁,发动机随之销毁) |
聚合 | 弱关联,整体与部分可独立存在,部分可被多个整体共享。 | 整体不管理部分的生命周期。 | 学校 与 学生 (学校关闭,学生仍存在) |
继承虽然能实现代码复用,但存在以下问题:
-
破坏封装性:子类依赖父类实现细节,父类修改可能影响所有子类。
-
类膨胀:继承层级过深易导致类爆炸(Class Explosion)。
-
灵活性差:无法在运行时动态切换行为(需通过子类化实现)。
-
违反单一职责原则:子类可能被迫继承无关方法。
直接上代码:
1.继承
abstract class Notifier {public abstract void send(String message);
}class EmailNotifier extends Notifier {@Overridepublic void send(String message) {System.out.println("发送邮件: " + message);}
}class SMSNotifier extends Notifier {@Overridepublic void send(String message) {System.out.println("发送短信: " + message);}
}// ❌ 问题:若需同时支持邮件和短信,需创建新子类,导致类膨胀
class EmailAndSMSNotifier extends Notifier { /* 冗余代码 */ }
2.组合/聚合
// 定义消息发送接口(抽象)
interface MessageSender {void send(String message);
}// 具体实现类
class EmailSender implements MessageSender {@Overridepublic void send(String message) {System.out.println("发送邮件: " + message);}
}class SMSSender implements MessageSender {@Overridepublic void send(String message) {System.out.println("发送短信: " + message);}
}// 通知服务通过组合复用发送功能
class NotificationService {private List<MessageSender> senders = new ArrayList<>();public void addSender(MessageSender sender) {senders.add(sender);}public void sendNotification(String message) {for (MessageSender sender : senders) {sender.send(message);}}
}// 使用示例
public class Client {public static void main(String[] args) {NotificationService service = new NotificationService();service.addSender(new EmailSender());service.addSender(new SMSSender());service.sendNotification("订单已支付"); // 同时发送邮件和短信}
}
组合/聚合复用原则通过对象间的协作而非继承层级,实现代码复用与功能扩展.
总结
开闭原则:要求对扩展开放,对修改关闭里氏替换原则:不要破坏继承体系依赖倒置原则:要求面向接口编程单一职责原则:实现类职责要单一接口隔离原则:在设计接口的时候要精简单一迪米特法则:只与直接的朋友的通信合成复用原则:尽量使用聚合和组合的方式,而不是使用继承
设计原则的核心思想
-
高内聚:模块内部元素紧密协作,职责单一。
-
低耦合:模块间依赖最小化,修改影响范围可控。
-
可维护性:代码易读、易扩展、易调试。
-
可测试性:通过解耦和依赖注入,便于单元测试和集成测试。
-
灵活性:适应需求变化,支持快速迭代。
相关文章:
Java进阶--面向对象设计原则
设计模式 概念 设计模式,又称软件设计模式,是一套被反复使用,经过分类编目的,代码设计经验的总结。描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方。它是解决特定问题的一系列套路,是…...
java每日精进 4.26【多租户之过滤器及请求处理流程】
一月没更,立誓以后断更三天我就是狗!!!!!!!! 研究多租户框架中一条请求的处理全流程 RestController RequestMapping("/users") public class UserControlle…...
【学习笔记】Stata
一、Stata简介 Stata 是一种用于数据分析、数据管理和图形生成的统计软件包,广泛应用于经济学、社会学、政治科学等社会科学领域。 二、Stata基础语法 2.1 数据管理 Stata 支持多种数据格式的导入,包括 Excel、CSV、文本文件等。 从 Excel 文件导入…...
[MySQL数据库] 事务与锁
🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…...
Rule.issuer(通过父路径配置loader处理器)
说明 正常在设置loader配置规则时,都是通过文件后缀来配置的 issuer的作用是可以通过父级的路径,设置生效的匹配规则 与rule的差别 test: 匹配当前模块的路径(如 .css 文件) issuer: 匹配引入当前模块的父模块的路径࿰…...
MyBatis 插件开发的完整详细例子
MyBatis 插件开发的完整详细例子 MyBatis 插件(Interceptor)允许开发者在已映射语句执行过程中的某一点进行拦截调用,从而实现自定义逻辑。以下是一个完整的 MyBatis 插件开发示例,涵盖所有使用场景,并附有详细注释和总…...
树状数组底层逻辑探讨 / 模版代码-P3374-P3368
目录 功能 实现 Q:但是,c[x]左端点怎么确定呢? Q:那么为什么要以二进制为基础呢? Q:为什么是补码 - ? 区间查询 树形态 性质1.对于x<y,要么c[x]和c[y]不交,要么c[x]包含于c[y] 性质2.c[x] 真包含 于c[x l…...
Eigen库入门
Eigen是一个C模板库,用于线性代数运算,包括矩阵、向量、数值求解和相关算法。它以其高性能、易用性和丰富的功能而闻名。 安装与配置 Eigen是一个纯头文件库,无需编译,只需包含头文件即可使用。 下载Eigen:从官方网站…...
力扣HOT100——102.二叉树层序遍历
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]] /*** Definition for a bi…...
客户案例 | 光热+数智双驱动!恒基能脉的数字化协同与技术创新实践
光热先锋 智领未来 恒基能脉新能源科技有限公司: 创新驱动,智造光热未来行业领航者 恒基能脉新能源科技有限公司是一家立足于光热发电核心技术产品,专注于“光热” 多能互补项目的国家高新技术企业,其核心产品定日镜广泛应用于光热发电、储…...
第十六周蓝桥杯2025网络安全赛道
因为只会web,其他方向都没碰过,所以只出了4道 做出来的: ezEvtx 找到一个被移动的文件,疑似被入侵 提交flag{confidential.docx}成功解出 flag{confidential.docx} Flowzip 过滤器搜索flag找到flag flag{c6db63e6-6459-4e75-…...
构造函数有哪些种类?
构造函数用于对象的初始化。 1.默认构造函数:没有参数,执行默认的初始化操作; 2.参数化构造函数:传入参数的构造函数,允许构造函数初始化成员变量; 3.拷贝构造函数:将同一类型的实例化对象作…...
第十六届蓝桥杯大赛软件赛省赛 C/C++ 大学B组 [京津冀]
由于官方没有公布题目的数据, 所以代码仅供参考 1. 密密摆放 题目链接:P12337 [蓝桥杯 2025 省 AB/Python B 第二场] 密密摆放 - 洛谷 题目描述 小蓝有一个大箱子,内部的长宽高分别是 200、250、240(单位:毫米)&…...
关于调度策略的系统性解析与物流机器人应用实践
关于调度策略的系统性解析与物流机器人应用实践 一、调度策略的定义与核心目标 调度策略是用于在复杂环境中协调资源分配、任务排序及路径规划的决策框架,旨在通过优化资源利用率和任务执行效率,实现系统整体性能的最优解。其核心目标包括: 动态适应性:应对实时变化(如订…...
探索具身智能协作机器人:技术、应用与未来
具身智能协作机器人:概念与特点 具身智能协作机器人,简单来说,就是将人工智能技术与机器人实体相结合,使其能够在与人类共享的空间中进行安全、高效协作的智能设备。它打破了传统机器人只能在预设环境中执行固定任务的局限&#…...
毕业项目-Web入侵检测系统
1. 项目简介 系统主要分为两大板块:靶标站点和入侵检测系统。靶标站点是系统的被监测对象,而入侵检测系统则是用于检测靶标站点的流量是否存在异常,以及在检测到异常时进行告警。 入侵检测系统的实现过程简述如下: 数据获取与分…...
【分布式系统中的“瑞士军刀”_ Zookeeper】二、Zookeeper 核心功能深度剖析与技术实现细节
在分布式系统的复杂生态中,Zookeeper 凭借其强大的核心功能,成为保障系统稳定运行的关键组件。上篇文章我们了解了 Zookeeper 的基础概念与安装配置,本文将继续深入剖析 Zookeeper 的核心功能,包括分布式锁、配置管理、命名服务和…...
前端学习笔记(四)自定义组件控制自己的css
1、前言及背景 自己写的一个组件有至少3个页面在使用,组件中的部分文字颜色需要统一修改需要根据一个状态字段来显示不同颜色且不希望受父组件影响 注意:博主学习vue截止目前也就半年,如有知识错误之处还请指出不胜感激,祝学习开…...
从描述语言,非功能性需求,需求和架构的一致性三个方面,说明软件需求到架构的映射存在哪些难点
软件需求到架构的映射是软件工程中的关键环节,其难点主要体现在描述语言差异、非功能性需求的复杂性以及需求与架构的一致性维护三个方面。以下是具体分析: 1. 描述语言的差异 难点:需求与架构使用不同的抽象语言描述,导致语义鸿…...
linux blueZ 第五篇:高阶优化与性能调优——蓝牙吞吐、延迟与功耗全攻略
本篇面向已有实战经验的读者,深入探讨 Classic Bluetooth 与 BLE 在 BlueZ 平台上的性能优化和调优方法,包括连接参数、MTU 调整、PHY 选择、缓存管理、并发策略,以及 HCI 抓包、功耗测量与自动化基准测试,助你打造高吞吐、低延迟、超低功耗的蓝牙应用。 目录 为何要做性能…...
linux的例行性工作(at)
使用场景: 生活中,我们有太多场景需要使用到闹钟,比如早上 7 点起床,下午 4 点开会,晚上 8 购物,等等 在 Linux 系统里,我们同样也有类似的需求。比如我们想在凌晨 1 点将文件上传服务器&#…...
JVM考古现场(二十六):执剑人·降维打击的终极审判
楔子:二向箔的颤动——当修真文明遭遇降维打击 "警告!老年代发生维度坍缩!"我腰间悬挂的昆仑镜突然迸发幽蓝光芒,终南山巅的河图洛书大阵中,GC日志正以《奇门遁甲》的格局疯狂演化: // 降维打击…...
腾讯云物联网平台
文档:物联网开发平台 MQTT.fx 快速接入物联网开发平台_腾讯云...
Unity之基于MVC的UI框架-含案例
Unity之基于MVC的UI框架-含案例 使用案例:类《双人成行》3D动作益智冒险类双人控制游戏开发教程 资源地址:https://learn.u3d.cn/tutorial/3d-adventure-william-anna 一、MVC框架概览 本框架以MVC的方式搭建,以View视口的方式展现数据&am…...
【Token系列】01 | Token不是词:GPT如何切分语言的最小单元
文章目录 01 | Token不是词:GPT如何切分语言的最小单元?一、什么是 Token?二、Token 是怎么来的?——BPE算法原理BPE核心步骤: 三、为什么不直接用词或字符?四、Token切分的实际影响五、中文Token的特殊性六…...
C++学习之路,从0到精通的征途:List类的模拟实现
目录 一.list的介绍 二.list的接口实现 1.结点 2.list结构 3.迭代器 (1)begin (2)end 4.修改 (1)insert (2)push_back (3)push_front ࿰…...
Java大师成长计划之第4天:Java中的泛型
📢 友情提示: 本文由银河易创AI(https://ai.eaigx.com)平台gpt-4o-mini模型辅助创作完成,旨在提供灵感参考与技术分享,文中关键数据、代码与结论建议通过官方渠道验证。 在现代软件开发中,类型安…...
计算机学报 2024年 区块链论文 录用汇总 附pdf下载
计算机学报 Year:2024 1 Title: 区块链中的公钥密码:设计、分析、密评与展望 Authors: Key words: 区块链;公钥密码算法;算法设计;复杂性分析;密评 Abstract: 比特币的成功,吸引了人们研…...
【Castle-X机器人】三、紫外消杀模块安装与调试
持续更新。。。。。。。。。。。。。。。 【Castle-X机器人】紫外消杀模块安装与调试 三、紫外消杀模块安装与调试2.1 安装2.2 调试2.2.1 紫外消杀模块话题2.2.2 测试 三、紫外消杀模块安装与调试 2.1 安装 使用相应工具将紫外消杀模块固定在Castle-X机器人底盘 2.2 调试 2.2…...
精益数据分析(29/126):深入剖析电子商务商业模式
精益数据分析(29/126):深入剖析电子商务商业模式 在创业和数据分析的学习道路上,我们始终在探索如何更精准地把握商业规律,提升业务的竞争力。今天,我们依旧怀揣着共同进步的愿望,深入解读《精…...
AI图像编辑器 Luminar Neo 便携版 Win1.24.0.14794
如果你对图像编辑有兴趣,但又不想花费太多时间学习复杂的软件操作,那么 Luminar Neo 可能就是你要找的完美工具。作为一款基于AI技术的创意图像编辑器,Luminar Neo简化了复杂的编辑流程,即使是没有任何图像处理经验的新手…...
在Mybatis中为什么要同时指定扫描mapper接口和 mapper.xml 文件,理论单独扫描 xml 文件就可以啊
设计考虑因素 历史兼容性: MyBatis早期版本主要依赖XML配置,后来才引入接口绑定方式同时支持两种方式可以保证向后兼容 明确性: 显式指定两种路径可以使映射关系更加明确减少因命名不一致导致的潜在问题 性能考虑: 同时扫描可…...
MyBatis XML 配置完整示例(含所有核心配置项)
MyBatis XML 配置完整示例(含所有核心配置项) 1. 完整 mybatis-config.xml 配置文件 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""htt…...
【数据结构入门训练DAY-24】美国大选
文章目录 前言一、题目二、解题思路结语 前言 本次训练内容 训练STL中sort的操作方法。训练解题思维。 一、题目 美国大选是按各州的投票结果来确定最终的结果的,如果得到超过一半的州的支 持就可以当选,而每个州的投票结果又是由该州选民投票产生…...
stm32L4R5ZI Nucleo-144 GPIO点灯及按键中断
文章目录 前言一、CubeMx环境配置二、GPIO点灯操作三、按键中断点灯总结 前言 STM32L4R5ZI Nucleo-144是STMicroelectronics推出的一款基于ARM Cortex-M4内核的微控制器芯片。它是STM32L4系列中的一员,针对低功耗和高性能的应用而设计。以下是一些关键特点和技术规格…...
访问Redis时遇到 unknown command ‘FT.INFO‘, with args beginning with 错误的解决方案
在B站学习 图灵程序员-诸葛 的LangChain入门课程《基于Redis保存历史聊天信息》。在实践代码时遇到了一些问题,在这里记录一下,希望能帮助到也在学习的同学。话不多说,上代码,这段代码使用langchain_redis来持久化大模型对话的聊天…...
Swift与iOS内存管理机制深度剖析
前言 内存管理是每一位 iOS 开发者都绕不开的话题。虽然 Swift 的 ARC(自动引用计数)极大简化了开发者的工作,但只有深入理解其底层实现,才能写出高效、健壮的代码,避免各种隐蔽的内存问题。本文将从底层原理出发&…...
数据库系统概论(五)关系模型的数据结构及形式化
数据库系统概论(五)关系模型的数据结构及形式化 前言一、关系:从“表格”说起1.1 关系数据模型中的“关系”是什么?1.2 域(Domain):数据的“类型限定”1.3 笛卡尔积(Cartesian Produ…...
Python类和对象四(十三)
魔法方法: 按位运算 按位于运算 只要相同才是1 或运算: 只要某个位是1结果就是1 、 按位非 将结果取反 按位异或: 左移和右移运算符: 右移两位 右移动n位,就是除以2的n次方 左移两位: 左移n位就是乘…...
Go 1.24 中的弱指针包 weak 使用介绍
在 Go 语言中,“弱指针”指的是不会阻止垃圾回收器(GC)回收目标对象的引用。 当一个对象只剩弱指针指向它,而没有任何强引用时,GC 仍会把该对象当作不可达对象并回收;随后,所有指向它的弱指针会…...
毕业项目-基于深度学习的入侵检测系统
选题背景与意义 随着互联网技术的飞速发展,网络在各个领域中的作用日益重要。然而,伴随着技术的进步,网络安全问题也愈加严峻,网络攻击事件频繁发生,给个人、企业乃至国家带来了巨大的经济损失与安全威胁。入侵检测系…...
Github 2025-04-26 Rust开源项目日报Top10
根据Github Trendings的统计,今日(2025-04-26统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10Dart项目1RustDesk: 用Rust编写的开源远程桌面软件 创建周期:1218 天开发语言:Rust, Dart协议类型:GNU Affero General Public Li…...
【Hive入门】Hive分桶表深度解析:从哈希分桶到Join优化的完整指南
目录 引言 1 分桶表基础概念 1.1 什么是分桶表 1.2 分桶与分区的区别 2 分桶表设计与创建 2.1 创建分桶表语法 2.2 分桶键选择原则 2.3 桶数确定策略 3 分桶表数据加载 3.1 标准数据加载流程 3.2 分桶表数据验证 4 分桶Join优化原理 4.1 Map端Join优化 4.2 Sort-…...
django之优化分页功能(利用参数共存及封装来实现)
优化分页功能 目录 1.封装分页代码 2.解决分页时覆盖搜索参数的bug 3.优化分页功能 上一篇文章我们讲到了搜索功能和分页展示数据功能。那这篇文章, 在上篇文章的基础上, 会去优化这些功能并解决搜索功能和分页功能不能一起使用的bug。 一、封装分页代码 原本我们的asse…...
linux blueZ 第四篇:BLE GATT 编程与自动化——Python 与 C/C++ 实战
本篇聚焦 BLE(Bluetooth Low Energy)GATT 协议层的编程与自动化实践,涵盖 GATT 基础、DBus API 原理、Python(dbus-next/bleak)示例、C/C++ (BlueZ GATT API)示例,以及自动发现、读写特征、订阅通知、安全配对与脚本化测试。 目录 BLE GATT 基础概念 BlueZ DBus GATT 模…...
前端面试每日三题 - Day 16
这是我为准备前端/全栈开发工程师面试整理的第16天每日三题练习,涵盖事件循环深入解析 、Vue3 响应式系统原理 ,以及 多租户系统设计实践。每道题附带 详细解析、示例代码与脑图建议,助你全面掌握底层原理与架构设计思维。 ✅ 题目 1…...
使用PyTorch实现简单图像识别(基于MNIST手写数字数据集)的完整代码示例,包含数据加载、模型定义、训练和预测全流程
以下是一个使用PyTorch实现简单图像识别(基于MNIST手写数字数据集)的完整代码示例,包含数据加载、模型定义、训练和预测全流程: import torch import torch.nn as nn import torch.optim as optim import torchvision import torc…...
【Android】四大组件之Activity
目录 一、什么是Activity 二、如何创建和配置Activity 三、Activity 跳转与数据传递 四、数据保存与恢复 五、Activity 启动模式 六、自定义返回行为 七、复杂界面布局 你可以把Activity想象成手机屏幕上的一个“页面”。比如,当你打开一个App时,…...
数据库原理(1)
第一章 概论 一、基本概念 数据(Data)是数据库中存储的基本对象,描述事物的符号记录。例如学生的学号、姓名等信息都是数据。 数据库(Database,DB)长期存储在计算机内、有组织的、可共享的大量数据的集合。…...
SQL盲注问题深度解析与防范策略
引言 在当今互联网时代,Web应用程序的安全性是重中之重。SQL注入作为一种常见且极具威胁性的攻击手段,而其中的SQL盲注更是因其隐蔽性强、难以察觉而备受关注。攻击者借助SQL盲注,在无法直接获取数据库返回结果的情况下,通过精心构造特殊的SQL语句,利用页面的不同响应来逐…...