Java事务之五——Template模式

本文介绍如何使用Template模式简化Java事务管理。通过定义TransactionTemplate类及其doJobInTransaction方法,实现在超类中处理事务的通用逻辑,而具体业务逻辑则由子类实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java事务之五——Template模式

                    本文转载自:http://www.cnblogs.com/davenkin/archive/2013/02/23/java-transaction-5.html,侵删。

  在本系列上一篇文章中,我们讲到了使用TransactionManger和ConnectionHolder完成线程安全的事务管理,在本篇中,我们将在此基础上引入Template模式进行事务管理。

 

  这是一个关于Java事务处理的系列文章,请通过以下方式下载github源代码:

git clone https://github.com/davenkin/java_transaction_workshop.git

 

  Template模式大家应该都很熟悉,比如Spring就提供了许多Template,像JdbcTemplate和JmsTemplate等。Template模式的基本思想是:在超类里将完成核心功能的方法声明为抽象方法,留给子类去实现,而在超类中完成一些通用操作,比如JMS的Session的建立和数据库事务的准备工作等。

 

  在本篇文章中,我们使用一个Template类来帮助管理事务,定义TransactionTemplate类如下:

复制代码
package davenkin.step4_transaction_template;

import davenkin.step3_connection_holder.TransactionManager;
import javax.sql.DataSource;

public abstract class TransactionTemplate
{
    private TransactionManager transactionManager;

    protected TransactionTemplate(DataSource dataSource)
    {
        transactionManager = new TransactionManager(dataSource);
    }

    public void doJobInTransaction()
    {
        try
        {
            transactionManager.start();
            doJob();
            transactionManager.commit();
        } catch (Exception e)
        {
            transactionManager.rollback();
        } finally
        {
            transactionManager.close();
        }
    }

    protected abstract void doJob() throws Exception;
}
复制代码

 

  在TransactionTemplate类中定义一个doJobInTransaction方法,在该方法中首先使用TransactionManager开始事务,然后调用doJob方法完成业务功能,doJob方法为抽象方法,完成业务功能的子类应该实现该方法,最后,根据doJob方法执行是否成功决定commit事务或是rollback事务。

 

  然后定义使用TransactionTemplate的TransactionTemplateBankService:

复制代码
package davenkin.step4_transaction_template;

import davenkin.BankService;
import davenkin.step3_connection_holder.ConnectionHolderBankDao;
import davenkin.step3_connection_holder.ConnectionHolderInsuranceDao;
import javax.sql.DataSource;

public class TransactionTemplateBankService implements BankService
{
    private DataSource dataSource;
    private ConnectionHolderBankDao connectionHolderBankDao;
    private ConnectionHolderInsuranceDao connectionHolderInsuranceDao;

    public TransactionTemplateBankService(DataSource dataSource)
    {
        this.dataSource = dataSource;
        connectionHolderBankDao = new ConnectionHolderBankDao(dataSource);
        connectionHolderInsuranceDao = new ConnectionHolderInsuranceDao(dataSource);
    }

    public void transfer(final int fromId, final int toId, final int amount)
    {
        new TransactionTemplate(dataSource)
        {
            @Override
            protected void doJob() throws Exception
            {
                connectionHolderBankDao.withdraw(fromId, amount);
                connectionHolderInsuranceDao.deposit(toId, amount);
            }
        }.doJobInTransaction();
    }
}
复制代码

 

  在TransactionTemplateBankService的transfer方法中,我们创建了一个匿名的TtransactionTemplate类,并且实现了doJob方法,在doJob方法中调用两个DAO完成业务操作,然后调用调用TransactionTemplateBankService的doJobInTransaction方法。

 

  由于TransactionTemplate只是对上一篇文章中事务处理的一层封装,故TransactionManager和两个DAO类都保持和上一篇中的一样,此时他们都使用SingleThreadConnectionHolder获得Connection,故事务处理成功。

 

  在下一篇文章中,我们会讲到使用Java的动态代理来完成事务处理,这也是Spring管理事务的典型方法。

<think>我们正在讨论Java中的模板方法设计模式。根据引用[1]和引用[2]的内容,模板方法模式是一种行为设计模式,它定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 模式结构: 1. 抽象类(Abstract Class):定义了一个模板方法(通常为final,防止子类重写整个算法结构),以及一些基本方法和抽象方法(由子类实现)。 2. 具体类(Concrete Class):实现抽象类中的抽象方法,完成特定步骤。 使用场景: 模板方法模式在需要定义算法框架,同时允许子类在不改变结构的情况下重写某些步骤时非常有用。例如,在Spring框架中的JDBCTemplate事务管理等。 示例代码(基于引用[1]的代码,稍作解释): 抽象类中定义了一个模板方法(templateMethod),它调用了多个步骤(step1, step2, step3)。其中step1和step3是具体方法(在抽象类中实现),step2是抽象方法,由子类实现。 下面我们详细解释示例代码: 抽象类(AbstractClass): - 模板方法(templateMethod)是final的,这样确保子类不能重写整个算法结构。 - step1和step3是私有方法,在抽象类中实现,子类无法修改。 - step2是抽象方法,由子类实现。 具体类(ConcreteClassA和ConcreteClassB): - 它们继承抽象类,并实现了step2方法,提供了各自不同的实现。 客户端代码(Client): - 创建具体类的实例,调用模板方法,将执行抽象类中定义的步骤序列,其中step2由具体类实现。 代码示例: ```java // 抽象类 public abstract class AbstractClass { // 模板方法,定义了算法的骨架(通常为final,防止子类覆盖整个算法) public final void templateMethod() { step1(); // 执行步骤1 step2(); // 执行步骤2,由子类实现 step3(); // 执行步骤3 } // 具体步骤1,私有方法,子类不可见,因此不可重写 private void step1() { System.out.println("Step 1"); } // 具体步骤2,抽象方法,由子类实现 protected abstract void step2(); // 具体步骤3,私有方法 private void step3() { System.out.println("Step 3"); } } // 具体类A public class ConcreteClassA extends AbstractClass { @Override protected void step2() { System.out.println("ConcreteClassA Step 2"); } } // 具体类B public class ConcreteClassB extends AbstractClass { @Override protected void step2() { System.out.println("ConcreteClassB Step 2"); } } // 客户端代码 public class Client { public static void main(String[] args) { AbstractClass concreteClassA = new ConcreteClassA(); concreteClassA.templateMethod(); // 输出:Step 1, ConcreteClassA Step 2, Step 3 AbstractClass concreteClassB = new ConcreteClassB(); concreteClassB.templateMethod(); // 输出:Step 1, ConcreteClassB Step 2, Step 3 } } ``` 运行结果: 当调用concreteClassA.templateMethod()时,输出: ``` Step 1 ConcreteClassA Step 2 Step 3 ``` 当调用concreteClassB.templateMethod()时,输出: ``` Step 1 ConcreteClassB Step 2 Step 3 ``` 模式优点: 1. 代码复用:将公共行为放在父类中,避免重复代码。 2. 扩展性好:子类可以通过实现抽象方法来扩展算法的部分步骤,符合开闭原则。 3. 控制反转:父类控制整个流程,子类实现具体细节。 模式缺点: 1. 每个不同的实现都需要一个子类,导致类的个数增加,系统更加庞大。 2. 父类中的抽象方法由子类实现,子类执行的结果会影响父类,这导致一种反向的控制结构。 实际应用: 在Spring框架中,JDBCTemplate就是一个典型的模板方法模式的应用。它定义了执行SQL语句的流程(如获取连接、创建语句、执行、处理结果、释放资源等),而具体的SQL操作和结果处理则由用户通过回调接口(如RowMapper)来实现。 总结: 模板方法模式通过固定算法骨架,将可变部分延迟到子类实现,提供了一种代码复用的重要技巧。在框架设计中,它常常被用来定义算法的骨架,而将具体的步骤实现交给用户。 §§相关问题§§ 1. 模板方法模式与策略模式有什么区别? 2. 在Spring框架中,模板方法模式有哪些具体应用? 3. 模板方法模式如何保证子类不能改变算法结构? 4. 模板方法模式中的钩子方法是什么?</think>### Java 模板方法设计模式详解 #### 模式定义 模板方法模式Template Method Pattern)是一种**行为型设计模式**,它定义了一个算法的骨架,将某些步骤延迟到子类实现。该模式的核心是: 1. **抽象类**定义算法框架(模板方法) 2. **具体子类**实现特定步骤 3. **防止子类修改算法结构**(通过final修饰模板方法) #### 模式结构(基于引用[1]示例) ```java // 1. 抽象类(定义算法骨架) public abstract class AbstractClass { // final修饰的模板方法(固定算法流程) public final void templateMethod() { step1(); // 固定步骤 step2(); // 可变步骤(子类实现) step3(); // 固定步骤 } private void step1() { // 私有方法,子类不可修改 System.out.println("Step 1"); } protected abstract void step2(); // 抽象方法,子类必须实现 private void step3() { System.out.println("Step 3"); } } // 2. 具体实现类A public class ConcreteClassA extends AbstractClass { @Override protected void step2() { // 实现可变步骤 System.out.println("ConcreteClassA Step 2"); } } // 3. 具体实现类B public class ConcreteClassB extends AbstractClass { @Override protected void step2() { System.out.println("ConcreteClassB Step 2"); } } // 4. 客户端调用 public class Client { public static void main(String[] args) { AbstractClass objA = new ConcreteClassA(); objA.templateMethod(); // 输出:Step1 → A-Step2 → Step3 AbstractClass objB = new ConcreteClassB(); objB.templateMethod(); // 输出:Step1 → B-Step2 → Step3 } } ``` #### 核心特点 1. **算法骨架固定** `templateMethod()` 方法用 `final` 修饰,确保子类不能修改算法流程[^1] 2. **步骤分离** - **固定步骤**:由父类实现(如 `step1()`, `step3()`) - **可变步骤**:通过抽象方法(如 `step2()`)交给子类实现 3. **好莱坞原则** "不要调用我们,我们会调用你" —— 父类控制流程,子类仅提供具体实现[^2] #### 模式优势 | 优势 | 说明 | |------|------| | **代码复用** | 公共代码集中在抽象类,避免重复 | | **扩展灵活** | 新增子类即可扩展新行为 | | **封装不变** | 保护核心算法不被修改 | | **符合开闭原则** | 对扩展开放(新增子类),对修改关闭(算法结构) | #### 实际应用场景 1. **框架开发** Spring的 `JdbcTemplate` 定义了数据库操作流程(获取连接、执行SQL、释放资源),具体SQL由用户实现[^2] 2. **算法框架** 加密算法中固定流程(初始化→加密→填充),具体加密步骤可扩展 3. **工作流引擎** 审批流程的固定步骤(提交→审核→归档),审核逻辑可定制 4. **跨平台开发** 跨平台UI框架中,绘制流程固定,具体渲染由平台实现 #### 模式变体:钩子方法 在模板方法中添加可选步骤: ```java public abstract class AbstractClass { public final void templateMethod() { step1(); step2(); if (needExtraStep()) { // 钩子方法 extraStep(); } step3(); } // 默认不执行额外步骤 protected boolean needExtraStep() { return false; } protected void extraStep() {} // 空实现 } public class ConcreteClassC extends AbstractClass { @Override protected boolean needExtraStep() { return true; // 启用额外步骤 } @Override protected void extraStep() { System.out.println("Custom Extra Step"); } } ``` #### 设计原则验证 | 原则 | 符合性 | |------|--------| | **单一职责** | 每个类只负责特定步骤 | | **开闭原则** | 扩展新行为无需修改模板 | | **里氏替换** | 子类可无缝替换父类 | | **依赖倒置** | 高层模块依赖抽象 | > 该模式Java核心库和主流框架中广泛应用,如`java.util.AbstractList`的`addAll()`是模板方法,具体`add()`由子类实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值