服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - 浅析Java模板方法的一种使用方式

浅析Java模板方法的一种使用方式

2023-03-06 13:59Tangjiacheng Java教程

模板方法说白了就是将一段代码模板化,将通用的代码段抽取出来,并提供一些自定义的接口去定制的特定位置的某些业务功能。本文主要来和大家聊聊它的一种使用方式,希望对大家有所帮助

为什么我会想到使用模板方法呢?

在日常开发中,我们经常需要使用编程式事务来解决一些实在的业务问题。以Hibernate框架为例(其实对于ORM框架来说,都大同小异。我们公司使用的是Hiberante,所以这里就以Hibernate为例了),我们实现一个编程式事务如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SessionFactory sessionFactory = (SessionFactory) applicationContext.getBean("sessionFactory");
Session session = sessionFactory.openSession();
try {
    session.beginTransaction();
    String sql = "update table set A = :a where id = :id";
    session.createNativeQuery(sql)
            .setParameter("a", "a")
            .setParameter("id", id)
            .executeUpdate();
    session.getTransaction().commit();
} catch (Exception e) {
    session.getTransaction().rollback();
} finally {
    session.close();
}

我们看上述的代码是不是有一种很乱的感觉,还要自己去写try{}catch{}finally{}。而且当我们代码中有很多地方都应用了编程式事务的话,那么我们的代码会显得有些臃肿。尤其对于我这种强迫症患者来说,哈哈!!

既然如此,我们肯定要想一种方式去优化一下,至少让它看起来更优美一些。我这里选择使用模板方法来改造一下。

什么是模板方法设计模式?

模板方法说白了就是将一段代码模板化,将通用的代码段抽取出来,并提供一些自定义的接口去定制的特定位置的某些业务功能。

根据我的理解,模板方法的核心思想就是 重写 。我们在模板中的指定位置提供一个外部可编辑的接口,让调用者可以根据需求去随意重写这个接口来达到他的目的。

其实在Spring中也广泛使用的模板方法,当我们学习Spring源码的时候会发现,实际上Bean的生命周期中就使用了模板方法。我们可以根据自己的需求在Bean生命周期的各个阶段去做一些事情。

代码优化

首先我们先维护一个抽象的模板类,这个类里包含了三个公开的方法,用来提供为调用者去定制使用。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public abstract class TransactionManagerTemplate {
 
    /**
     * 处理事务中的实际要处理的业务代码
     */
    public void handle() {}
 
    /**
     * 异常处理
     */
    public void exceptionHandle() {}
 
    /**
     * finally处理
     */
    public void finallyHandle() {}
 
}

然后我们创建一个事务管理器,封装一个runTransaction方法,里面就包含了上面那边不忍直视的代码。然后我们将Session和抽象的模板类作为参数传入

并且将抽象的模板类中的三个公开方法填入到try{}catch{}finally{}中的各个位置。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
@Component
public class TransactionManager {
 
    @Autowired
    private ApplicationContext applicationContext;
 
    /**
     * 默认SessionFactory
     */
    public static final String DEFAULT_SESSION_FACTORY = "sessionFactory";
 
 
    /**
     * 执行事务
     * @param session
     * @param transactionManagerTemplate
     *
     * 使用案例:
     * Session session = transactionManager.getSession();
     * transactionManager.runTransaction(session, new TransactionManagerTemplate() {
     *     // 实际要重写的接口
     * });
     */
    public void runTransaction(Session session, TransactionManagerTemplate transactionManagerTemplate) {
        try {
            session.beginTransaction();
            transactionManagerTemplate.handle();
            session.getTransaction().commit();
        } catch (Exception e) {
            transactionManagerTemplate.exceptionHandle();
            session.getTransaction().rollback();
        } finally {
            transactionManagerTemplate.finallyHandle();
            session.close();
        }
    }
 
    /**
     * 获取默认SessionFactory
     * @return
     */
    public SessionFactory getSessionFactory() {
        return getSessionFactory(DEFAULT_SESSION_FACTORY);
    }
 
    /**
     * 获取指定SessionFactory
     * @param beanName      指定SessionFactory的BeanName
     * @return
     */
    public SessionFactory getSessionFactory(String beanName) {
        SessionFactory sessionFactory = (SessionFactory) applicationContext.getBean(beanName);
        if(sessionFactory == null) {
            throw new BAPException("不存在BeanName为【{}】的SessionFactory", beanName);
        }
        return sessionFactory;
    }
 
    /**
     * 获取默认Session
     * @return
     */
    public Session getSession() {
        return getSessionFactory(DEFAULT_SESSION_FACTORY).openSession();
    }
 
    /**
     * 获取指定SessionFactory下的Session
     * @param sessionFactoryBeanName      指定SessionFactory的BeanName
     * @return
     */
    public Session getSession(String sessionFactoryBeanName) {
        return getSessionFactory(sessionFactoryBeanName).openSession();
    }
 
}

我们在业务代码中想要再次使用编程式事务时,就可以通过如下方式调用:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Session session = transactionManager.getSession();
transactionManager.runTransaction(session, new TransactionManagerTemplate() {
    @Override
    public void handle() {
        // try中要添加的业务逻辑
    }
 
    @Override
    public void exceptionHandle() {
        // catch中要添加的业务逻辑
    }
 
    @Override
    public void finallyHandle() {
        // finally中要添加的业务逻辑
    }
});

看,这是不是更美观了一些呀!

以上就是浅析Java模板方法的一种使用方式的详细内容,更多关于Java模板方法的资料请关注服务器之家其它相关文章!

原文链接:https://juejin.cn/post/7202888932744806461

延伸 · 阅读

精彩推荐
  • Java教程解决SpringBoot log4j日志没生成的问题

    解决SpringBoot log4j日志没生成的问题

    这篇文章主要介绍了解决SpringBoot log4j日志没生成的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...

    桑汤奈伊伏12722021-10-25
  • Java教程Spring中使用atomikos+druid实现经典分布式事务的方法

    Spring中使用atomikos+druid实现经典分布式事务的方法

    这篇文章主要介绍了Spring中使用atomikos+druid实现经典分布式事务的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看...

    冯立彬4782019-06-30
  • Java教程JAVA中对List进行查询

    JAVA中对List进行查询

    下面小编就为大家带来一篇在java List中进行模糊查询的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    _东门吹雪9292021-11-15
  • Java教程Java中的泛型方法详解及简单实例

    Java中的泛型方法详解及简单实例

    这篇文章主要介绍了Java中的泛型方法详细介绍的相关资料,需要的朋友可以参考下...

    java教程网2242020-07-18
  • Java教程浅谈Java中Unicode的编码和实现

    浅谈Java中Unicode的编码和实现

    这篇文章向大家介绍了Java编程中Unicode编码及实现的相关内容,列举了几个字符不同表达式的比较,以及Unicode平面映射的知识,具有一点点参考价值,需要...

    凝静志远9382021-01-24
  • Java教程Spring MVC数据绑定概述及原理详解

    Spring MVC数据绑定概述及原理详解

    这篇文章主要介绍了Spring MVC数据绑定概述及原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以...

    曾强2062020-06-29
  • Java教程IDEA版使用Java操作Redis数据库的方法

    IDEA版使用Java操作Redis数据库的方法

    这篇文章主要介绍了IDEA版使用Java操作Redis数据库的方法,首先需要下载jedis.jar包,然后再工程中设置具体操作步骤跟随小编一起学习下吧...

    一棵小白杨站在哨所旁8562021-08-07
  • Java教程JAVA线程同步实例教程

    JAVA线程同步实例教程

    这篇文章主要介绍了JAVA线程同步实例教程,在Java程序设计中有着非常广泛的应用,需要的朋友可以参考下 ...

    shichen20144892019-11-27