概述
在模板方法模式中,可以将子类共性的部分放在父类中实现,而特性的部分延迟到子类中实现,只需将特性部分在父类中声明成抽象方法即可,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤,不同的子类可以以不同的方式来实现这些逻辑。(在模板方法模式中,我们可以将相同部分的代码放在父类中,而将不同的代码放入不同的子类中,从而解决代码重复的问题。)
模板方法模式的优点在于符合“开闭原则”,也能够实现代码复用,将不变的行为转移到父类,去除子类中的重复代码。
代码演示
package com.fh.templates;
import org.junit.Test;
public class TemplatesTest {
@Test
public void m() {
ExaminationPape pape = new Student();
pape.result();
System.out.println("--------------");
pape = new Teacher();
pape.result();
}
abstract class ExaminationPape {
public void result() {
System.out.println("1+1=" + answer1());
System.out.println("1+2=" + answer2());
System.out.println("1-1=" + answer3());
}
public abstract String answer1();
public abstract String answer2();
public abstract String answer3();
}
class Student extends ExaminationPape {
@Override
public String answer1() {
return "2";
}
@Override
public String answer2() {
return "4";
}
@Override
public String answer3() {
return "1";
}
}
class Teacher extends ExaminationPape {
@Override
public String answer1() {
return "2";
}
@Override
public String answer2() {
return "3";
}
@Override
public String answer3() {
return "0";
}
}
}
使用场景
spring 事务
源码解析
AbstractPlatformTransactionManager类
//模板方法doRollback(),把重要的步骤延迟到子类去实现
protected abstract void doRollback(DefaultTransactionStatus status) throws TransactionException;
//模板方法doCommit(),把重要的步骤延迟到子类去实现
protected abstract void doCommit(DefaultTransactionStatus status) throws TransactionException;
@Override
public final void commit(TransactionStatus status) throws TransactionException {
//省略...
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
if (defStatus.isLocalRollbackOnly()) {
//省略...
//调用processRollback()
processRollback(defStatus, false);
return;
}
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
//省略...
//调用processRollback()
processRollback(defStatus, true);
return;
}
//调用processCommit()
processCommit(defStatus);
}
//这个方法定义了骨架,里面会调用一个doRollback()的模板方法
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
if (status.hasSavepoint()) {
//省略...
}
else if (status.isNewTransaction()) {
//调用doRollback()模板方法
doRollback(status);
}
else {
//省略...
}
//省略了很多代码...
}
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
//省略...
if (status.hasSavepoint()) {
//省略...
}
else if (status.isNewTransaction()) {
//省略...
//调用doCommit()模板方法
doCommit(status);
}
else if (isFailEarlyOnGlobalRollbackOnly()) {
unexpectedRollback = status.isGlobalRollbackOnly();
}
//省略了很多代码...
}
其实模板模式在日常开发中也经常用,比如一个方法中,前后代码都一样,只有中间有一部分操作不同,就可以使用模板模式进行优化代码,这可以大大地减少冗余的代码,非常实用。
DataSourceTransactionManager
模板方法则由各种事务管理器的实现类去实现,也就是把骨架中重要的doRollback()延迟到子类。一般来说,Spring默认是使用的事务管理器的实现类是DataSourceTransactionManager。
//通过继承AbstractPlatformTransactionManager抽象类
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
implements ResourceTransactionManager, InitializingBean {
//重写doCommit()方法,实现具体commit的逻辑
@Override
protected void doCommit(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Committing JDBC transaction on Connection [" + con + "]");
}
try {
con.commit();
}
catch (SQLException ex) {
throw new TransactionSystemException("Could not commit JDBC transaction", ex);
}
}
//重写doRollback()方法,实现具体的rollback的逻辑
@Override
protected void doRollback(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
}
try {
con.rollback();
}
catch (SQLException ex) {
throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
}
}
}
如果你是用Hibernate框架,Hibernate也有自身的实现HibernateTransactionManager,这就体现了设计模式的开闭原则,通过继承或者组合的方式进行扩展,而不是直接修改类的代码。
标签:status,...,子类,void,方法,public,模板 From: https://www.cnblogs.com/haveanicedayfh/p/17761842.html