跟着Mybatis 学习 23 种设计模式

以下是 MyBatis 框架中涉及的 23 种设计模式的分类、技术原理及代码示例:

一、创建型模式

1. 工厂方法模式 (Factory Method)

作用:定义创建对象的接口,由子类决定实例化哪个类。

MyBatis 实现

  • SqlSessionFactory:通过 SqlSessionFactoryBuilder 构建 SqlSessionFactory 实例。
public class SqlSessionFactoryBuilder {
    public SqlSessionFactory build(InputStream inputStream) {
        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream);
        return build(parser.parse()); // 解析配置并构建实例
    }
}

// 具体实现(DefaultSqlSessionFactory)
public class DefaultSqlSessionFactory implements SqlSessionFactory {
    private final Configuration configuration;

    @Override
    public SqlSession openSession() {
        return new DefaultSqlSession(configuration); // 创建会话实例
    }
}
2. 抽象工厂模式 (Abstract Factory)

作用:创建一组相关或依赖的对象,而无需指定具体类。

MyBatis 实现

  • Environment:通过 Environment 抽象工厂创建 DataSourceTransactionFactory
public class Environment {
    private final String id;
    private final TransactionFactory transactionFactory;
    private final DataSource dataSource;

    public Environment(String id, TransactionFactory transactionFactory, DataSource dataSource) {
        this.id = id;
        this.transactionFactory = transactionFactory;
        this.dataSource = dataSource;
    }

    public DataSource getDataSource() {
        return dataSource;
    }
}
3. 单例模式 (Singleton)

作用:确保一个类只有一个实例,并提供全局访问点。

MyBatis 实现

  • ErrorContext:通过线程局部变量保证每个线程拥有唯一的 ErrorContext 实例。
public class ErrorContext {
    private static final ThreadLocal<ErrorContext> LOCAL = new ThreadLocal<>();

    public static ErrorContext instance() {
        ErrorContext context = LOCAL.get();
        if (context == null) {
            context = new ErrorContext();
            LOCAL.set(context);
        }
        return context;
    }
}
4. 建造者模式 (Builder)

作用:逐步构建复杂对象,允许用户通过链式调用设置属性。

MyBatis 实现

  • SqlSessionFactoryBuilder:通过链式调用构建 SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
    .build(Resources.getResourceAsStream("mybatis-config.xml"));
5. 原型模式 (Prototype)

作用:通过克隆现有对象创建新实例。

MyBatis 实现

  • MappedStatement:通过克隆 MappedStatement 创建新的语句对象。
public class MappedStatement implements Cloneable {
    @Override
    public MappedStatement clone() {
        return (MappedStatement) super.clone(); // 浅克隆
    }
}

二、结构型模式

6. 适配器模式 (Adapter)

作用:将接口转换为客户端期望的另一个接口。

MyBatis 实现

  • Log 接口适配器:适配不同日志框架(如 SLF4J、Log4j)。
public class Slf4jLoggerImpl implements Log {
    private final org.slf4j.Logger logger;

    public Slf4jLoggerImpl(String clazz) {
        logger = org.slf4j.LoggerFactory.getLogger(clazz);
    }

    @Override
    public boolean isDebugEnabled() {
        return logger.isDebugEnabled();
    }

    @Override
    public void debug(String message) {
        logger.debug(message);
    }
}
7. 装饰器模式 (Decorator)

作用:动态为对象添加附加功能。

MyBatis 实现

  • Cache 装饰器:为缓存添加附加功能(如淘汰策略)。
public class FifoCache implements Cache {
    private final Cache delegate;
    private final List<Object> keyList = new LinkedList<>();

    @Override
    public void putObject(Object key, Object value) {
        if (keyList.size() >= size) {
            Object oldestKey = keyList.remove(0);
            delegate.removeObject(oldestKey); // 移除最旧元素
        }
        keyList.add(key);
        delegate.putObject(key, value);
    }
}
8. 代理模式 (Proxy)

作用:通过代理对象控制对原对象的访问。

MyBatis 实现

  • Mapper 接口代理:通过 JDK 动态代理生成 Mapper 接口的实现类。
public class MapperProxy<T> implements InvocationHandler {
    private final SqlSession sqlSession;
    private final Class<T> mapperInterface;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
        }
        return sqlSession.selectOne(method.getName(), args); // 调用具体方法
    }
}
9. 外观模式 (Facade)

作用:为复杂子系统提供简化的接口。

MyBatis 实现

  • SqlSession:封装数据库操作,提供统一的访问接口。
public interface SqlSession {
    <T> T selectOne(String statement, Object parameter);
    int insert(String statement, Object parameter);
    int update(String statement, Object parameter);
    int delete(String statement, Object parameter);
}
10. 桥接模式 (Bridge)

作用:将抽象与实现解耦,使两者可以独立变化。

MyBatis 实现

  • Transaction 接口:桥接不同事务实现(如 JDBC、JTA)。
public interface Transaction {
    Connection getConnection() throws SQLException;
    void commit() throws SQLException;
    void rollback() throws SQLException;
}

// 具体实现(JdbcTransaction)
public class JdbcTransaction implements Transaction {
    @Override
    public Connection getConnection() {
        return dataSource.getConnection(); // 返回 JDBC 连接
    }
}
11. 组合模式 (Composite)

作用:将对象组合成树形结构,以表示“部分-整体”的层次结构。

MyBatis 实现

  • SqlNode 组合:通过组合模式构建动态 SQL。
public interface SqlNode {
    boolean apply(DynamicContext context);
}

// 具体节点(IfSqlNode)
public class IfSqlNode implements SqlNode {
    private final String test;
    private final SqlNode contents;

    @Override
    public boolean apply(DynamicContext context) {
        if (evaluator.evaluateBoolean(test, context.getBindings())) {
            contents.apply(context); // 递归应用子节点
            return true;
        }
        return false;
    }
}
12. 享元模式 (Flyweight)

作用:共享对象以减少内存占用。

MyBatis 实现

  • MappedStatement 复用:通过 Configuration 缓存 MappedStatement 对象。
public class Configuration {
    protected final Map<String, MappedStatement> mappedStatements = new StrictMap<>();

    public MappedStatement getMappedStatement(String id) {
        return mappedStatements.get(id); // 从缓存获取
    }
}

三、行为型模式

13. 模板方法模式 (Template Method)

作用:定义算法骨架,将某些步骤延迟到子类实现。

MyBatis 实现

  • BaseExecutor:定义数据库操作流程,子类实现具体步骤。
public abstract class BaseExecutor implements Executor {
    @Override
    public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds) {
        // 公共逻辑(如缓存处理)
        return doQuery(ms, parameter, rowBounds); // 调用子类实现
    }

    protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds);
}
14. 观察者模式 (Observer)

作用:定义对象间的一对多依赖,当一个对象状态改变时,所有依赖者收到通知。

MyBatis 实现

  • 事件监听机制:通过 EventListener 监听数据库操作事件。
public interface EventListener {
    void onEvent(Event event);
}

// 具体监听器(LogEventListener)
public class LogEventListener implements EventListener {
    @Override
    public void onEvent(Event event) {
        System.out.println("Event occurred: " + event.getType());
    }
}
15. 策略模式 (Strategy)

作用:定义一系列算法,并将每个算法封装起来,使它们可以互换。

MyBatis 实现

  • StatementHandler 策略:根据数据库类型选择不同的 SQL 执行策略。
public interface StatementHandler {
    Statement prepare(Connection connection) throws SQLException;
    void parameterize(Statement statement) throws SQLException;
}

// 具体策略(SimpleStatementHandler)
public class SimpleStatementHandler implements StatementHandler {
    @Override
    public Statement prepare(Connection connection) {
        return connection.createStatement(); // 返回简单语句
    }
}
16. 命令模式 (Command)

作用:将请求封装为对象,以便用不同的请求、队列或日志参数化其他对象。

MyBatis 实现

  • RoutingStatementHandler:封装 SQL 执行命令。
public class RoutingStatementHandler implements StatementHandler {
    private final StatementHandler delegate;

    public RoutingStatementHandler(ExecutorType executorType, StatementHandler handler) {
        this.delegate = handler;
    }

    @Override
    public Statement prepare(Connection connection) {
        return delegate.prepare(connection); // 执行具体命令
    }
}
17. 责任链模式 (Chain of Responsibility)

作用:将请求的发送者和接收者解耦,使多个对象都有机会处理请求。

MyBatis 实现

  • 插件拦截器链:通过 InterceptorChain 处理插件拦截。
public class InterceptorChain {
    private final List<Interceptor> interceptors = new ArrayList<>();

    public Object pluginAll(Object target) {
        for (Interceptor interceptor : interceptors) {
            target = interceptor.plugin(target); // 依次应用拦截器
        }
        return target;
    }
}
18. 备忘录模式 (Memento)

作用:捕获并保存对象的内部状态,以便后续恢复。

MyBatis 实现

  • BoundSql 状态保存:通过 BoundSql 保存 SQL 语句和参数。
public class BoundSql {
    private final String sql;
    private final List<ParameterMapping> parameterMappings;

    public BoundSql(String sql, List<ParameterMapping> parameterMappings) {
        this.sql = sql;
        this.parameterMappings = parameterMappings;
    }

    public String getSql() {
        return sql;
    }
}
19. 状态模式 (State)

作用:允许对象在内部状态改变时改变行为。

MyBatis 实现

  • 事务状态管理:通过 TransactionState 管理事务的不同状态。
public enum TransactionState {
    ACTIVE,
    COMMITTED,
    ROLLED_BACK
}

// 事务状态管理
public class Transaction {
    private TransactionState state = TransactionState.ACTIVE;

    public void commit() {
        state = TransactionState.COMMITTED; // 修改状态
    }
}
20. 访问者模式 (Visitor)

作用:在对象结构中定义新操作,而无需修改结构本身。

MyBatis 实现

  • Node 访问者:通过 XMLScriptBuilder 访问和修改 SQL 节点。
public interface Node {
    void accept(Visitor visitor);
}

// 具体访问者(XMLScriptBuilder)
public class XMLScriptBuilder implements Visitor {
    @Override
    public void visit(TextNode node) {
        // 处理文本节点
    }

    @Override
    public void visit(IfSqlNode node) {
        // 处理 If 节点
    }
}
21. 解释器模式 (Interpreter)

作用:给定一种语言,定义其文法表示,并构建解释器来解释语言中的句子。

MyBatis 实现

  • OGNL 表达式解析:通过 OgnlCache 解析动态 SQL 中的表达式。
public class OgnlCache {
    public static Object getValue(String expression, Object root) {
        return Ognl.getValue(expression, root); // 解析表达式
    }
}
22. 迭代器模式 (Iterator)

作用:提供一种顺序访问集合元素的方法,而无需暴露其内部表示。

MyBatis 实现

  • 结果集遍历:通过 ResultSetWrapper 遍历查询结果。
public class ResultSetWrapper {
    private final ResultSet resultSet;

    public Iterator<Object> iterator() {
        return new ResultSetIterator(resultSet); // 返回迭代器
    }
}
23. 中介者模式 (Mediator)

作用:定义一个中介对象来封装一系列对象之间的交互。

MyBatis 实现

  • SqlSession 作为中介者:协调 ExecutorStatementHandler 等组件之间的交互。
public class DefaultSqlSession implements SqlSession {
    private final Configuration configuration;
    private final Executor executor;

    @Override
    public <T> T selectOne(String statement, Object parameter) {
        return executor.query(configuration.getMappedStatement(statement), parameter, RowBounds.DEFAULT).get(0);
        // 协调 Executor 执行查询
    }
}

总结

MyBatis 框架通过灵活运用 23 种设计模式,实现了高扩展性、低耦合性和灵活性。这些模式覆盖了对象创建、结构组织、行为交互等各个方面,是学习 Java 框架设计的经典案例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值