好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

浅析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模板方法的一种使用方式的详细内容...

  阅读:15次