java设计模式(9):模板方法模式(TemplateMethod)

        一,定义:模板方法模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。


           二,类图:

java设计模式(9):模板方法模式(TemplateMethod)


           三,通过小例子讲解:

            这个模式一般用在程序的步骤比较多,而且有固定的模式,固定的步骤,而每一步的实现又有多种情况,这是我们可以使用TemplateMethod模式。这样可以保证算法骨架的正确性,又将多态运用的非常好。

          这里举个人一天要做的事情吧,假如一个人一天要有起床,吃饭,做事情,睡觉四个事项。

           1,首先我们看模板类:

  1.     /** 
  2.      * 模板方法设计模式中的“模板类” 
  3.      * 一般情况下模板类都是一个抽象类 
  4.      */  
  5.     public abstract class PersonDay {  
  6.       
  7.         /** 
  8.          * 在模板方法中编写核心算法,这个算法是不会改变的,这个算法被子类继承,可以得到复用。 
  9.          * 模板方法的流程一般不让子类覆盖,不希望子类去重新定义核心算法,所以模板方法通常被final修饰 
  10.          */  
  11.         public final void day(){  
  12.             doGetUp();  
  13.             doEatBreakfast();  
  14.             doSome();  
  15.             doSleep();  
  16.         }  
  17.           
  18.         //将行为的具体实现延迟到子类中完成,达到不同的实现效果。  
  19.         public abstract void doGetUp();  
  20.         public abstract void doEatBreakfast();  
  21.         public abstract void doSome();  
  22.         public abstract void doSleep();  
  23.     }  

       2,我们来看学生类:

  1.   public class StudentDay extends PersonDay{  
  2.                  //学生起床  
  3.             public  void doGetUp(){  
  4.                 System.out.println("学生起床了,准备上学了")  
  5.             }  
  6.               
  7.               
  8.             //吃早餐  
  9.             public void doEatBreakfast(){  
  10.                 System.out.println("学生吃早餐:牛奶、面包");  
  11.             }  
  12.               
  13.             //上学  
  14.             public void doSome(){  
  15.                 System.out.println("学生上课学习");  
  16.             }  
  17.               
  18.             //睡觉  
  19.             public void doSleep(){  
  20.                 System.out.println("学生做完功课睡觉");  
  21.             }  
  22.               
  23.         }  

       3,我们来看老师类:

  1.      public class StudentDay extends PersonDay{  
  2.              //老师起床  
  3.         public  void doGetUp(){  
  4.             System.out.println("老师起床了,安顿好家人,准备到学校工作")  
  5.         }  
  6.           
  7.           
  8.         //吃早餐  
  9.         public void doEatBreakfast(){  
  10.             System.out.println("老师早餐:小米粥、油条");  
  11.         }  
  12.           
  13.         //教学  
  14.         public void doSome(){  
  15.             System.out.println("老师上课教学");  
  16.         }  
  17.           
  18.         //睡觉  
  19.         public void doSleep(){  
  20.             System.out.println("老师备完功课睡觉");  
  21.         }  
  22.           
  23.     }    

     其它子类…………

          4,看一下测试类,非常简单:


  1.   public class Test {  
  2.       
  3.         public static void main(String[] args) {  
  4.             //父类指向子类  
  5.             PersonDay d1 = new StudentDay();  
  6.             d1.day();  
  7.               
  8.             PersonDay d2 = new WorkerDay();  
  9.             d2.day();  
  10.         }  
  11.       
  12.     }  
  13. </span>  



           分析总结:这样我们就利用模板方法完成了这个实例,我们来分析其中的特点吧:

         1,将不变的核心算法行为搬移到了父类,去除了子类中的重复代码,并保证了算法的正确性,因为就在父类中写了一次。

         2,具体步骤的下放,使多态体现了其中的优势,使代码的扩展性更高!



 

        四,应用:

             大家都知道在我们编写Servlet之前需要我们将之在web.xml中进行配置,这样我们才能在jspServlet中传递数据,并从之获取数据,才能完成我们网页的动态显示。但是随着功能的增多,Servlet的增多,就需要我们为每个Servlet进行配置,这样有两个缺点:1,不断的进行web.xml文件配置不仅麻烦而且会使其容量越来越大,负载也会变大;2,每个servlet需要我们继承HttpServlet,这样耦合性比较高。为了解决此,我们这里可以使用模板方法进行解决。

 

          如果根据数据库中的表进行分类的话,我们一般对表的操作可以分成增删改查,四种操作,这里我们进行上移,看模板类:

  1.    /** 
  2.      * 模板类,以后编写的servlet类需要继承这个类,而不是httpservlet类了 
  3.      * @author Administrator 
  4.      */  
  5.     public abstract class CommonServlet extends HttpServlet {  
  6.       
  7.         @Override  
  8.         //模板方法,定义了算法  
  9.         protected void service(HttpServletRequest request, HttpServletResponse response)  
  10.                 throws ServletException, IOException {  
  11.               
  12.             //获取执行的类型  
  13.             String operationType=request.getParameter("operationType");  
  14.               
  15.             //判断  
  16.             if("insert" .equals(operationType)){  
  17.                 doInsert(request,response);  
  18.             }else if("select".equals(operationType)){  
  19.                 doSelect(request,response);  
  20.             }else if("update".equals(operationType)){  
  21.                 doUpdate(request,response);  
  22.             }else{  
  23.                 //.......................  
  24.             }  
  25.               
  26.         }  
  27.           
  28.         //抽象方法,都需要实现  
  29.         protected abstract void doInsert(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException;  
  30.         protected abstract void doSelect(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException;  
  31.         protected abstract void doUpdate(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException;  
  32.       
  33.     }  
  34. </span>  

           当然那些增删改查的的servlet就需要继承这个类了:

  1. public class AuthServlet extends CommonServlet {  
  2.     private IAuthService authService=new AuthServiceImpl();  
  3.     @Override  
  4.     protected void doInsert(HttpServletRequest request,  
  5.             HttpServletResponse response) throws ServletException, IOException {  
  6.             //根据不同的表插入方法的具体实现  
  7.     }  
  8.   
  9.     @Override  
  10.     protected void doSelect(HttpServletRequest request,  
  11.             HttpServletResponse response) throws ServletException, IOException {  
  12.             //根据不同表查询方法的具体实现  
  13.     }  
  14.   
  15.     @Override  
  16.     protected void doUpdate(HttpServletRequest request,  
  17.             HttpServletResponse response) throws ServletException, IOException {  
  18.         //根据表的不同,更新方法的具体实现。  
  19.     }  
  20. }  
  21. </span>  

           这里注意我们在jsp页面进行相关功能时,需要我们将operationType执行的类别传过来,方便我们顶层Servlet的判断。这个就是框架抽象的很小很小的一步,但是对于这个模版方法阐释的也是很好的。