当前位置: 首页 > news >正文

MyBatis中使用的设计模式详细解析

一、单例模式

1. 使用位置

  • SqlSessionFactory:用于创建SqlSession对象的工厂。

2. 设计原因

  • 节省资源SqlSessionFactory负责管理数据库连接,如果每次都创建新的实例,会浪费很多资源。

3. 功能实现

  • 全局访问:在整个应用中只使用一个SqlSessionFactory实例,方便统一管理。

4. 简单例子

想象一下一个“打印机”,只有一个打印机可以为整个公司打印文件。每个人都可以使用这个打印机,而不是每个人都买一个。

public class SqlSessionFactorySingleton {private static SqlSessionFactory instance; // 存储SqlSessionFactory的唯一实例private SqlSessionFactorySingleton() {} // 私有构造函数,防止外部直接创建实例public static SqlSessionFactory getInstance() {if (instance == null) { // 如果实例不存在synchronized (SqlSessionFactorySingleton.class) { // 加锁,确保线程安全if (instance == null) { // 再次检查实例instance = new SqlSessionFactoryBuilder().build(inputStream); // 创建实例}}}return instance; // 返回单例实例}
}

二、工厂模式

1. 使用位置

  • SqlSessionFactory:用于创建SqlSession对象的具体工厂。

2. 设计原因

  • 解耦合:将对象的创建和使用分开,方便更换实现。

3. 功能实现

  • 灵活性:可以在不修改代码的情况下更换SqlSession的实现。

4. 简单例子

想象你要买车,你不需要关心每个车的制造过程,只需要一个“车商”给你提供车就可以了。

public interface SqlSessionFactory {SqlSession openSession(); // 定义一个方法,用于创建SqlSession
}public class DefaultSqlSessionFactory implements SqlSessionFactory {@Overridepublic SqlSession openSession() {return new DefaultSqlSession(); // 创建并返回DefaultSqlSession的实例}
}

三、代理模式

1. 使用位置

  • MapperProxy:拦截对Mapper接口方法的调用。

2. 设计原因

  • 动态代理:在运行时为Mapper接口生成实现类,避免重复代码。

3. 功能实现

  • 方法拦截:可以在调用Mapper方法时添加额外的处理,比如记录日志。

4. 简单例子

想象你有一个“秘书”,每当你需要做一件事时,秘书会帮你处理一些细节,比如安排时间和准备材料。

public class MapperProxy<T> implements InvocationHandler {private final SqlSession sqlSession; // 用于执行SQL的SqlSession实例private final Class<T> mapperInterface; // Mapper接口的Class对象public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface) {this.sqlSession = sqlSession; // 初始化SqlSessionthis.mapperInterface = mapperInterface; // 初始化Mapper接口}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 生成SQL语句的ID,并调用SqlSession执行SQLreturn sqlSession.selectOne(getStatement(method), args); // 执行SQL}private String getStatement(Method method) {// 生成SQL语句ID,格式为"Mapper接口名.方法名"return mapperInterface.getName() + "." + method.getName();}
}

四、模板方法模式

1. 使用位置

  • SqlSessionTemplate:提供一些基本的数据库操作方法。

2. 设计原因

  • 代码复用:将一些共同的操作封装在一个地方,避免重复代码。

3. 功能实现

  • 简化操作:开发者可以使用SqlSessionTemplate提供的基本操作,而不需要重复编写相同的代码。

4. 简单例子

想象你有一个“食谱”,每次做饭时,你只需要按照食谱的步骤去做,而不需要每次都重新想一遍。

public class SqlSessionTemplate implements SqlSession {private final SqlSessionFactory sqlSessionFactory; // SqlSessionFactory实例// 构造函数,接受SqlSessionFactory作为参数public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {this.sqlSessionFactory = sqlSessionFactory; // 初始化SqlSessionFactory}@Overridepublic <T> T selectOne(String statement, Object parameter) {// 执行查询操作,返回单个结果// 这里可以写具体的查询逻辑return null; // 这里是示例,实际实现中会返回查询结果}// 其他数据库操作方法可以在这里实现
}

五、观察者模式

1. 使用位置

  • 二级缓存失效机制:当数据库中的数据发生变化时,相关的缓存会被清除。

2. 设计原因

  • 数据一致性:确保多个缓存能够自动响应数据库的变化。

3. 功能实现

  • 自动更新:当数据发生变化时,相关的缓存会被自动清除,避免数据过时的问题。

4. 简单例子

想象一个“通知系统”,当一个人改变了他的联系方式,所有相关的人都会收到通知,确保他们的信息是最新的。

观察者接口
public interface Observer {void update(String message); // 更新方法,接受通知
}
具体观察者(缓存)
public class Cache implements Observer {private String cacheData; // 缓存的数据@Overridepublic void update(String message) {// 当接收到更新通知时,清空缓存System.out.println("Cache is being cleared due to: " + message);cacheData = null; // 清空缓存}// 模拟更新缓存数据的方法public void setCacheData(String data) {this.cacheData = data;}public String getCacheData() {return cacheData; // 返回缓存的数据}
}
主题(数据库)
import java.util.ArrayList;
import java.util.List;public class Database {private List<Observer> observers = new ArrayList<>(); // 存储观察者// 添加观察者public void addObserver(Observer observer) {observers.add(observer);}// 移除观察者public void removeObserver(Observer observer) {observers.remove(observer);}// 更新数据库的方法public void updateData(String newData) {// 模拟数据更新System.out.println("Database is updated with new data: " + newData);notifyObservers("Data updated to: " + newData); // 通知所有观察者}// 通知所有观察者private void notifyObservers(String message) {for (Observer observer : observers) {observer.update(message); // 调用观察者的更新方法}}
}
主程序
public class Main {public static void main(String[] args) {Database database = new Database(); // 创建数据库实例Cache cache = new Cache(); // 创建缓存实例database.addObserver(cache); // 将缓存添加为观察者// 模拟数据更新database.updateData("New User Data"); // 更新数据库数据}
}

6. 运行结果

当运行上面的代码时,会看到如下输出:

Database is updated with new data: New User Data
Cache is being cleared due to: Data updated to: New User Data
  • Observer接口:定义了一个更新方法,供具体观察者实现。
  • Cache类:实现了Observer接口,当数据库数据更新时,它会清空自己的缓存。
  • Database类:作为主题,负责管理观察者,并在数据更新时通知它们。
  • Main类:作为主程序,创建数据库和缓存的实例,并模拟数据更新。

六、策略模式

1. 使用位置

  • 插件机制:MyBatis支持通过插件机制来增强功能。

2. 设计原因

  • 灵活性和可扩展性:可以在运行时选择不同的插件策略。

3. 功能实现

  • 功能增强:通过不同的插件,可以实现日志记录、性能监控等功能,而不需要修改MyBatis的核心代码。

4. 简单例子

想象你有一个“工具箱”,你可以根据需要选择不同的工具来完成特定的任务,比如锤子、螺丝刀等。

public class MyPlugin implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 在调用目标方法前,可以进行一些处理System.out.println("Before executing: " + invocation.getMethod().getName());// 调用原方法并返回结果return invocation.proceed(); // 执行目标方法}@Overridepublic Object plugin(Object target) {// 将目标对象包装成插件return Plugin.wrap(target, this); // 返回插件对象}@Overridepublic void setProperties(Properties properties) {// 设置插件的属性}
}

七、总结

  • 单例模式:确保一个类只有一个实例,节省资源,方便管理。
  • 工厂模式:将对象创建与使用分开,增加灵活性。
  • 代理模式:动态生成接口的实现类,方便扩展功能。
  • 模板方法模式:封装公共逻辑,简化操作。
  • 观察者模式:保持数据一致性,自动更新缓存。
  • 策略模式:实现功能扩展,允许灵活选择不同的策略。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 基于python的web框架 Flask 入门基础知识【1】
  • pnpm 查看库的所有版本
  • Centos设置IP地址方法
  • flutter执行Asset中的可执行文件
  • 嵌入式Linux应用程序开发-2 Linux基础命令
  • 国外服务器独立ip的好处
  • 动态规划的正确打开
  • Linux学习-上传本地镜像到指定镜像仓库
  • Spring Boot DevTools:简化开发,实现热部署
  • 【自由能系列(初级)】大脑功能与贝叶斯计算——深层生成模型的自由能原理
  • (每日一问)计算机网络:浏览器输入一个地址到跳出网页这个过程中发生了哪些事情?(废话少说版)
  • Harmony南向驱动开发: HDC与真机调试
  • OmniGraffle Pro for Mac 思维导图软件安装
  • 《自然语言处理》—— jieba库的介绍与使用
  • 上新!Matlab实现基于QRGRU-Attention分位数回归门控循环单元注意力机制的时间序列区间预测模型
  • Centos6.8 使用rpm安装mysql5.7
  • classpath对获取配置文件的影响
  • ES10 特性的完整指南
  • github指令
  • JSONP原理
  • mongodb--安装和初步使用教程
  • Otto开发初探——微服务依赖管理新利器
  • Python 基础起步 (十) 什么叫函数?
  • React as a UI Runtime(五、列表)
  • React+TypeScript入门
  • SAP云平台里Global Account和Sub Account的关系
  • spring boot 整合mybatis 无法输出sql的问题
  • spring学习第二天
  • 第2章 网络文档
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 讲清楚之javascript作用域
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 软件开发学习的5大技巧,你知道吗?
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 思否第一天
  • 微信开放平台全网发布【失败】的几点排查方法
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 用jQuery怎么做到前后端分离
  • ​ubuntu下安装kvm虚拟机
  • ​补​充​经​纬​恒​润​一​面​
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • $(selector).each()和$.each()的区别
  • (160)时序收敛--->(10)时序收敛十
  • (Forward) Music Player: From UI Proposal to Code
  • (二)学习JVM —— 垃圾回收机制
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (附源码)ssm本科教学合格评估管理系统 毕业设计 180916
  • (蓝桥杯每日一题)love
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (原創) 未来三学期想要修的课 (日記)
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • .net core Swagger 过滤部分Api
  • .NET Framework .NET Core与 .NET 的区别
  • .NET 药厂业务系统 CPU爆高分析
  • .net反编译的九款神器