新车
preparecall(MyBatis设计模式之装饰器、模板方法、策略模式)

作为Java开发者,你一定用过MyBatis,但你真的了解它背后的设计精髓吗?本文将带你深入MyBatis装饰器、模板方法、策略三大设计模式的实战应用,看完保证你的代码水平暴涨!


开篇:为什么要学习MyBatis的设计模式?

MyBatis作为国内最流行的持久层框架之一,其源码中设计模式的运用堪称教科书级别。今天我们就来拆解其中最核心的3种模式:

✅ 装饰器模式 - 像搭积木一样动态添加功能✅ 模板方法模式 - 定义骨架,细节交给子类✅ 策略模式 - 算法随意切换,解耦到极致

第一式:装饰器模式 - 功能叠加的艺术

什么是装饰器模式?

想象你开了一家奶茶店,基础款是纯牛奶,客户可以加珍珠、加椰果、加布丁...每加一样就是一层"装饰"。装饰器模式就是这个道理——不改变原对象,动态添加新功能

MyBatis设计模式之装饰器、模板方法、策略模式nerror="javascript:errorimg.call(this);">

装饰器模式

MyBatis中的经典案例:CachingExecutor

MyBatis的二级缓存就是用装饰器模式实现的!看核心代码:

public class CachingExecutor implements Executor {    private final Executor delegate;  // 被装饰的真正执行器    private final TransactionalCacheManager tcm;    public CachingExecutor(Executor delegate) {        this.delegate = delegate;    }    @Override    public <E> List<E> query(...) throws SQLException {        Cache cache = ms.getCache();        if (cache != null) {            // 先查缓存            List<E> list = tcm.getObject(cache, key);            if (list == null) {                // 缓存没有,委托给原执行器查询                list = delegate.query(...);                // 放入缓存                tcm.putObject(cache, key, list);            }            return list;        }        // 没开缓存,直接用原执行器        return delegate.query(...);    }}

关键点:

  • CachingExecutor包装了一个真正的Executor
  • 先查缓存,没有才调用被包装的Executor
  • 完全不修改原Executor的代码!

Cache装饰器链 - 乐高式组装

更牛的是MyBatis的缓存系统,多个装饰器可以层层嵌套:

MyBatis设计模式之装饰器、模板方法、策略模式nerror="javascript:errorimg.call(this);">

Cache装饰器链

MyBatis提供了10种Cache装饰器:

装饰器

功能

使用场景

LruCache

LRU淘汰算法

内存有限时

FifoCache

FIFO淘汰算法

简单场景

SoftCache

软引用

防止OOM

WeakCache

弱引用

临时缓存

BlockingCache

防缓存击穿

高并发场景

LoggingCache

日志统计

监控缓存命中率

ScheduledCache

定时清理

定期刷新数据

SerializedCache

序列化存储

分布式缓存

SynchronizedCache

线程同步

保证线程安全

TransactionalCache

事务支持

配合事务使用

核心代码示例:

// LruCache - 最近最少使用淘汰public class LruCache implements Cache {    private final Cache delegate;    private Map<Object, Object> keyMap;    @Override    public void putObject(Object key, Object value) {        delegate.putObject(key, value);        cycleKeyList(key);  // 触发LRU淘汰    }}// BlockingCache - 防止缓存击穿public class BlockingCache implements Cache {    private final Cache delegate;    private final ConcurrentHashMap<Object, CountDownLatch> locks;    @Override    public Object getObject(Object key) {        acquireLock(key);  // 加锁        Object value = delegate.getObject(key);        if (value != null) {            releaseLock(key);  // 有值则释放锁        }        return value;    }}

装饰器模式的优势

✅ 不修改原类 - 通过包装扩展功能✅ 动态组合 - 运行时灵活添加功能✅ 职责单一 - 每个装饰器只做一件事✅ 无限嵌套 - 像搭积木一样组合功能

第二式:模板方法模式 - 框架设计的基石

什么是模板方法模式?

就像做菜有固定步骤:备菜→炒制→调味→装盘,但每道菜的具体做法不同。模板方法模式就是定义算法骨架,具体步骤由子类实现

MyBatis设计模式之装饰器、模板方法、策略模式nerror="javascript:errorimg.call(this);">

模板方法模式

MyBatis中的baseExecutor

baseExecutor是模板方法模式的经典案例,它定义了SQL执行的标准流程:

public abstract class baseExecutor implements Executor {    // 模板方法 - 定义查询的整体流程    @Override    public <E> List<E> query(...) throws SQLException {        // 1. 创建缓存Key        CacheKey key = createCacheKey(...);                List<E> list;        queryStack++;                // 2. 检查一级缓存        list = localCache.getObject(key);        if (list != null) {            return list;  // 缓存命中        }                // 3. 缓存未命中,查询数据库        list = queryFromDatabase(...);                // 4. 放入缓存        localCache.putObject(key, list);        return list;    }    // 抽象方法 - 由子类实现具体查询逻辑    protected abstract <E> List<E> doQuery(...);        protected abstract int doUpdate(...);}

三种Executor子类实现

MyBatis设计模式之装饰器、模板方法、策略模式nerror="javascript:errorimg.call(this);">

Executor策略选择

1️⃣ SimpleExecutor - 最简单直接

public class SimpleExecutor extends baseExecutor {    @Override    protected <E> List<E> doQuery(...) {        Statement stmt = null;        try {            // 每次都创建新Statement            stmt = createStatement(...);            // 执行查询            return handler.query(stmt, resultHandler);        } finally {            closeStatement(stmt);  // 用完就关闭        }    }}

2️⃣ ReuseExecutor - 重用Statement

public class ReuseExecutor extends baseExecutor {    private final Map<String, Statement> statementMap = new HashMap<>();    @Override    protected <E> List<E> doQuery(...) {        String sql = boundSql.getSql();        // 尝试重用已有的Statement        Statement stmt = statementMap.get(sql);        if (stmt == null) {            stmt = prepareStatement(...);            statementMap.put(sql, stmt);  // 缓存起来        }        return handler.query(stmt, resultHandler);    }}

3️⃣ BatchExecutor - 批量执行

public class BatchExecutor extends baseExecutor {    private final List<Statement> statementList = new ArrayList<>();    @Override    protected int doUpdate(...) {        // 不立即执行,先加入批处理列表        handler.batch(stmt);        return BATCH_UPDATE_RETURN_VALUE;    }    @Override    public List<BatchResult> doFlushStatements(...) {        // 统一执行所有批处理        for (Statement stmt : statementList) {            stmt.executeBatch();        }        return results;    }}

三种Executor对比

Executor类型

特点

适用场景

性能

SimpleExecutor

每次新建Statement

普通查询

⭐⭐⭐

ReuseExecutor

重用Statement

相同SQL多次执行

⭐⭐⭐⭐

BatchExecutor

批量执行

大量插入/更新

⭐⭐⭐⭐⭐

模板方法模式的威力

✅ 代码复用 - 公共逻辑在父类,避免重复✅ 扩展灵活 - 新增子类很简单✅ 流程统一 - 保证算法结构一致✅ 易于维护 - 修改流程只需改父类

第三式:策略模式 - 算法自由切换

什么是策略模式?

就像出行方式:走路、骑车、开车、坐地铁,目的地相同但策略不同。策略模式就是定义一系列算法,让它们可以互相替换

MyBatis设计模式之装饰器、模板方法、策略模式nerror="javascript:errorimg.call(this);">

RoutingStatementHandler

MyBatis中的RoutingStatementHandler

RoutingStatementHandler根据SQL类型自动选择合适的处理器:

public class RoutingStatementHandler implements StatementHandler {    private final StatementHandler delegate;    public RoutingStatementHandler(...) {        // 根据SQL类型选择策略        switch (ms.getStatementType()) {            case STATEMENT:                delegate = new SimpleStatementHandler(...);                break;            case PREPARED:                delegate = new PreparedStatementHandler(...);                break;            case CALLABLE:                delegate = new CallableStatementHandler(...);                break;        }    }    @Override    public int update(Statement statement) {        // 委托给具体策略执行        return delegate.update(statement);    }}

三种StatementHandler策略

核心区别代码示例:

// SimpleStatementHandler - 直接执行SQLString sql = "SELECT * FROM user WHERe id = 1";statement.execute(sql);// PreparedStatementHandler - 预编译SQL(推荐)String sql = "SELECt * FROM user WHERe id = ?";PreparedStatement ps = connection.prepareStatement(sql);ps.setInt(1, userId);ps.execute();// CallableStatementHandler - 调用存储过程String sql = "{call getUserById(?)}";CallableStatement cs = connection.prepareCall(sql);cs.setInt(1, userId);cs.execute();

Executor的策略选择

MyBatis启动时可以配置使用哪种Executor:

public class Configuration {    public Executor newExecutor(Transaction tx, ExecutorType type) {        Executor executor;        // 策略选择        if (ExecutorType.BATCH == type) {            executor = new BatchExecutor(this, tx);        } else if (ExecutorType.REUSE == type) {            executor = new ReuseExecutor(this, tx);        } else {            executor = new SimpleExecutor(this, tx);        }                // 如果开启缓存,再装饰一层        if (cacheEnabled) {            executor = new CachingExecutor(executor);        }        return executor;    }}

策略模式的强大之处

✅ 算法解耦 - 使用和实现分离✅ 易于切换 - 运行时动态选择✅ 易于扩展 - 新增策略很简单✅ 消除if-else - 代码更优雅

三大模式的协同作战

MyBatis的强大之处在于多种模式的完美配合:

MyBatis设计模式之装饰器、模板方法、策略模式nerror="javascript:errorimg.call(this);">

设计模式综合应用

// 一个完整的SQL执行流程// 1. 策略模式 - 选择Executor类型Executor executor = configuration.newExecutor(    transaction,     ExecutorType.SIMPLE  // 选择策略);// 2. 装饰器模式 - 添加缓存功能if (cacheEnabled) {    executor = new CachingExecutor(executor);  // 装饰}// 3. 模板方法模式 - 执行查询// baseExecutor定义流程:// 创建CacheKey → 查一级缓存 → 调用doQuery()List<User> users = executor.query(...);

装饰器模式适用场景

适合:

1.需要动态添加功能(日志、缓存、权限)2.不想通过继承扩展(避免类爆炸)3.需要组合多个功能

不适合:

1.功能简单固定2.性能要求极高(多层嵌套有开销)

模板方法模式适用场景

适合:

1.算法结构固定,部分步骤可变2.多个类有相同的处理流程3.需要控制子类扩展点

不适合:

1.流程经常变化2.子类差异太大

策略模式适用场景

适合:

1.多种算法可互相替换2.需要运行时选择算法3.消除大量if-else

不适合:

1.策略很少变化2.客户端需要了解所有策略

模式选择速查表

需求

推荐模式

原因

动态添加功能

装饰器

灵活组合,不改原类

算法流程固定

模板方法

代码复用,扩展方便

算法需要切换

策略

解耦使用和实现

创建复杂对象

建造者

分步构建

对象创建分类

工厂

统一创建入口

总结:从MyBatis学到的设计智慧

装饰器模式:

1.CachingExecutor为Executor加缓存2.Cache装饰器链实现LRU、FIFO等功能3.核心思想:包装而非继承

模板方法模式:

1.baseExecutor定义SQL执行流程2.SimpleExecutor、ReuseExecutor、BatchExecutor实现细节3.核心思想:定义骨架,细节可变

策略模式:

1.RoutingStatementHandler路由到不同Handler2.Executor类型可配置切换3.核心思想:算法解耦,自由替换

设计模式的价值

MyBatis设计模式之装饰器、模板方法、策略模式nerror="javascript:errorimg.call(this);">

Mybatis整体架构

写在最后

MyBatis作为国内最流行的持久层框架,其源码中的设计模式应用堪称教科书。学设计模式不是为了炫技,而是为了写出更优雅、更易维护的代码。


顶一下()     踩一下()

热门推荐

发表评论
0评