`
aladdin_leon
  • 浏览: 118851 次
  • 性别: Icon_minigender_1
  • 来自: 哈尔滨
社区版块
存档分类
最新评论

关于Template Method模式的思考

阅读更多

     首先让我们看看生活之中的“模板”,在《设计模式-JAVA语言中的应用》是这样说的:“模板(Template)是指在薄片塑料板上面写字(或印字)后挖空,再使用毛笔或色笔涂满挖空的部分,就能看到纯手工而又不失工整的字样。看到模板上挖空形状,马上就知道最后会变出什么样的字,不过实际上所显示出来的字样还是要依使用的画笔的种类而定。拿黑色签字笔当画笔,成果当然就是签字笔风的字样;光是铅笔来画,得到的也就是灰黑色的铅笔字;如果用五颜六色的彩色笔,自然能创造出让人眼花缭乱的多色字样。但是,无论使用那种文具,制造出来的字样都还是脱不了模板上已经固定的形状。”这个例子想必日常生活中我们都见过吧!不过这和我们要讨论的Template Method有什么关系呢?
     Template Method模式的目的:定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中。
     看一个具体的例子,假如一个工作流由三个步骤来完成,执行的顺序为123依次执行,而每一个具体的步骤可能根据具体情况会有所不同,那麽我们制造如下的一个“薄片塑料板”:     最后让我们来看看如何制作出来不同的“字体”吧!   

  1. public abstract class WorkFlow {   
  2.       public abstract void stepOne();   
  3.       public abstract void stepTwo();   
  4.       public abstract void stepThree();   
  5.       public final void work() {   
  6.           stepOne();   
  7.           stepTwo();   
  8.           stepThree();   
  9.       }   
  10. }   

     注意关键字final的意义,它意味其子类不能对工作步骤的顺序进行修改,对于abstract,我们可能意识到它并不像我们开始时认为的那麽无用了,这里的用法也是抽象类的真正含义之一。下面我们来造作两种不同的“笔风”:

  1. public class WorkFlowOne extends WorkFlow {   
  2.       public void stepOne() {   
  3.          ......   
  4.       }   
  5.       public void stepTwo() {   
  6.          ......     
  7.       }   
  8.       public void stepThree() {   
  9.          ......   
  10.       }   
  11. }   
  12.   
  13. public class WorkFlowTwo extends WorkFlow {   
  14.       public void stepOne() {   
  15.          ......   
  16.       }   
  17.       public void stepTwo() {   
  18.          ......     
  19.       }   
  20.       public void stepThree() {   
  21.          ......   
  22.       }   
  23. }  

      最后让我们来看看如何制作出来不同的“字体”吧!

  1. WorkFlow one = new WorkFlowOne();   
  2. one.work();   
  3. WorkFlow two = new WorkFlowTwo();   
  4. two.work();   

      其实学习设计模式的难点,并不是记住这个模式的类图,或者是代码框架,重要的是理解思想,说的容易做起来就很难了,我们很难识别在具体的情况下该使用什么模式,其实我们不必为此而灰心,我们可以首先让我们的代码实现功能,然后在不影响代码功能的基础之上对代码进行重新的设计,重构为合适的模式。这样对于我们使用模式的难度就会减少了很多。
     如何把自己的代码重构为模板方法模式呢?首先我们要将类似方法的框架抽象出来,并将方法框架上移至超类中,而子类只需要提供在算法的实现过程中有所区别的那些步骤。不过需要补充一下,上面的重构是基于继承的,实际应用中,我们也可以将方法框架上移至“模板类”中,通过组合来实现模板方法模式。下面就让我们实战一下吧!
     看过了《深入浅出Hibernate》后,借此对其中关于借助模板模式对DAO重构总结一下,首先我们看一个在Hibernate下典型的DAO代码模板:

  1. public class UserDAO implements IUserDAO {   
  2.        ......   
  3.        public void saveUser(final User user) {   
  4.             Session session = null;   
  5.             Transation tx = null;   
  6.             try {   
  7.                  Configuration config = new Configuration().configure();   
  8.                  SessionFactory factory = config.buildSessionFactory();   
  9.                  session = factory.openSession();   
  10.                  tx = session.beginTransaction();   
  11.                  session.save(user);   
  12.                  tx.commit();   
  13.             } catch(HibernateException e) {   
  14.                  if(tx != null) {   
  15.                      try {   
  16.                           tx.rollback();   
  17.                       } catch(HibernateException e) {   
  18.                            ......   
  19.                       }   
  20.                  }   
  21.                  ......   
  22.             } finally {   
  23.                 if(session != null) {   
  24.                      try {   
  25.                          session.close();   
  26.                      } catch(HibernateException e) {   
  27.                          ......   
  28.                      }   
  29.                 }   
  30.             }   
  31.        }   
  32.         ......   
  33.  }   

     如果继续写下去,比如deleteUser、updateUser方法,会发现大部分的代码是没有任何变化的,只有兰颜色的部分发生了变化,似乎我们嗅到了代码里面一些不好的味道...既然他们都是一样的,那麽我们就会想到是否可以进行提取而形成一个模板呢?不过这里我们用的是基于Template与Callback的方法这样可以通过组合而不是继承的方式来使用模板,至于组合和继承的怎么选择,可以看看我的2006-10-16的日志《继承还是关联?是个问题》       

  1.  public class HibernateTemlate {   
  2.         public final Object run(HibernateCallback callback) {   
  3.            Session sesion = null;   
  4.            Transaction tx = null;   
  5.            try {   
  6.               session = RootDAO.createSession();   
  7.               tx = session.beginTransaction();   
  8.               Object result = callback.execute();   
  9.               tx.commit();   
  10.               session.flush();   
  11.               return result;   
  12.            } catch(HibernateException e) {   
  13.               if(tx != null) {   
  14.                  try {   
  15.                     tx.rollback();   
  16.                  } catch(Throwable t){   
  17.                     
  18.                  } throw new RuntimeException(e);   
  19.               }   
  20.            } finally {   
  21.               if(session != null) {   
  22.                  try {   
  23.                     session.close();   
  24.                  } catch(HibernateException e) {   
  25.                     throw new RuntimeException(e);   
  26.                  }   
  27.               }   
  28.            }   
  29.         }   
  30.  }  

      下面是回调接口的定义:

  1. public interface HibernateCallback {   
  2.         Object execute() throws HibernateException;   
  3. }   

      这就是我们进行了重新设计后的UserDAO:   

  1. public class UserDAO implements IUserDAO {   
  2.       ......   
  3.       public void saveUser(final User user) {   
  4.           new HibernateTemplate().run(new HibernateCallback() {   
  5.               public Object execute() throws HibernateException {   
  6.                   UserDAO userDAO = UserDAO.getInstance();   
  7.                   return userDAO.save(user);   
  8.              }   
  9.           });   
  10.       }   
  11.       ......   
  12. }   

      现在屏住呼吸,让我们看一看这段代码,它实现了上面代码一样的功能:

  1. public class UserDAO extends HibernateDaoSupport implements IUserDAO {   
  2.       public void saveUser(User user) {   
  3.            getHibernateTemplate().saveOrUpdate(user);   
  4.       }   
  5.       ......   
  6. }   

     你是不是有一点惊异呢!简直太简单了,这就是Spring+Hiberbate带给我们的春天,这里并没有详细介绍如何配置上面的代码,我们只是看一下冰山一角,就已经足够见识其简单性和纯洁性了,代码只关心最重要的业务逻辑,而不用在为繁杂的异常处理和事务声明而费心了。这里Spring利用的也恰恰是Template Method模式!
     不知道为什么写完这篇文章,好像对设计模式的认识清晰了一些,又好像更加模糊了,也许“道”亦有道...这其中的玄机也许只有靠每日的积累才能真正领悟吧...

分享到:
评论

相关推荐

    工厂模式及模板方法模式深度思考

    文件名"templatemethod"和"factory"暗示了博主可能分别展示了这两种模式的实例代码或者类结构。 总结来说,工厂模式和模板方法模式是面向对象设计的重要工具,它们可以帮助我们更好地组织代码,降低耦合,提高代码...

    《java设计模式》课后习题模拟试题解答——刘伟.zip

    3. **行为型模式**:包括策略(Strategy)、模板方法(Template Method)、观察者(Observer)、迭代器(Iterator)、访问者(Visitor)、责任链(Chain of Responsibility)、命令(Command)、备忘录(Memento)、...

    [Java设计模式(第2版)(Design.Patterns.in.Java).John.Metsker

    第21章 模板方法(template method)模式 182 第22章 状态(state)模式 193 第23章 策略(strategy)模式 204 第24章 命令(command)模式 213 第25章 解释器(interpreter)模式 221 第26章 扩展型模式介绍 236 第27章 装饰...

    Csharp设计模式电子版--一本很好C#设计模式

    命令模式(Command)、解释器模式(Interpreter)、迭代器模式(Iterator)、访问者模式(Visitor)、备忘录模式(Memento)、观察者模式(Observer)、状态模式(State)、策略模式(Strategy)、模板方法模式...

    设计模式视频课程PPT

    比如命令模式(Command)、解释器模式(Interpreter)、迭代器模式(Iterator)、中介者模式(Mediator)、备忘录模式(Memento)、观察者模式(...Strategy)、模板方法模式(Template Method)和访问者模式(Visitor)...

    Head.First设计模式_PDF

    3. 行为型模式:这类模式关注对象之间的交互和职责分配,包括策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、迭代器模式(Iterator)、命令模式(Command)、责任链模式(Chain ...

    设计模式精解-GoF23_种设计模式解析

    Template Method模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。这种模式常用于定义算法的基本框架,但允许子类修改...

    HeadFirst设计模式英文版

    这些模式包括但不限于单例模式(Singleton)、工厂方法模式(Factory Method)、抽象工厂模式(Abstract Factory)、建造者模式(Builder)、...策略模式、模板方法模式(Template Method)、访问者模式(Visitor)等...

    中文版_源码设计模式解析与实战.pdf

    4. **行为型模式**:如策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、命令模式(Command)、迭代器模式(Iterator)、访问者模式(Visitor)、责任链模式(Chain of ...

    刘艺模式编程附书源码

    3. 行为型模式:如策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、迭代器模式(Iterator)、命令模式(Command)、责任链模式(Chain of Responsibility)、备忘录模式(Memento...

    C++设计模式基础教程.pdf

    13. 模板方法模式(Template Method Pattern):使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 14. 命令模式(Command Pattern):将一个请求封装为一个对象,从而使你可用不同的请求对客户端...

    HeadFirst设计模式源码(部分)

    行为型模式关注对象间如何交互,如观察者(Observer)、策略(Strategy)和模板方法(Template Method)等。 源码中可能包含以下设计模式的应用: 1. **单例模式**(Singleton):确保一个类只有一个实例,并提供...

    GOF设计模式双语版(设计模式经典之作)

    模板方法模式(Template Method)定义了一个操作中的算法骨架,而将一些步骤延迟到子类中;访问者模式(Visitor)定义了一个访问结构元素的接口,并为该结构的每个类都提供了一个访问者类。 《GOF设计模式双语版》...

    23种设计模式(C++).pdf

    1. **Template Method模式**:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 2. **Strategy模式**:定义了一系列的算法,并将每一个...

    Java 中的设计模式 - jdon

    模板方法模式(Template Method)定义操作中的算法骨架,而将一些步骤延迟到子类中;还有职责链模式(Chain of Responsibility),使得多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合。 4. ...

    最全的软件设计模式(很全面)

    而无需暴露其底层表示,模版方法模式(Template Method)定义操作的框架,让子类填充具体步骤,观察者模式(Observer)定义对象间的一对多依赖关系,当一个对象的状态改变时,所有依赖于它的对象都会得到通知并自动...

    Head First 设计模式(中文版.pdf

    行为型模式则关注对象之间的交互和职责分配,如观察者模式(Observer)、模板方法模式(Template Method)、命令模式(Command)、迭代器模式(Iterator)、策略模式(Strategy)、状态模式(State)、访问者模式...

    CC++与设计模式讲义.pdf

    13. 模板方法模式(Template Method Pattern),在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。 14. 命令模式(Command Pattern),将请求封装为对象,从而使你可用不同的请求对客户端进行参数化。 15...

    Head First 设计模式

    如工厂模式(Factory Method)、抽象工厂模式(Abstract Factory)、单例模式(Singleton)、建造者模式(Builder)、原型模式(Prototype)、...Strategy)、模板方法模式(Template Method)以及访问者模式(Visitor)...

Global site tag (gtag.js) - Google Analytics