模板方法模式

问题

A模块 和 B模块 完全分开,互相独立,但是重复和相似的代码太多,不便扩展。

解决思路

将重复或相似的代码抽取出来,做成公共的功能,不同的控制就去扩展公共功能,也就是:将相似的运算步骤看做算法的骨架作为父类,具体的不同的步骤放到子类中实现。

模板方法

  • 定义

    定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。

    父类实现的就是不变的方法和算法的骨架,而需要变化的地方,都通过抽象方法,而子类就通过实现这些抽象方法完成特定的功能。
  • 结构
    • AbstractClass:抽象类(父类)。定义算法的骨架和原语操作,还可以提供算法通用的实现。(必有)
    • ConcreteClass:具体类(子类)。重定义父类的原子操作,完成特定子类的功能。(必有)
    • 具体的AbstractClass操作:辅助的公共功能。父类实现某些公共功能,给子类使用。
    • 钩子操作:子类选择地覆写父类的具体的操作,已提供新的实现来扩展功能。
    • 原语操作:父类的抽象方法,需要子类来实现。(必有)
    • Factory Method:父类中,需要某些对象的实例,可以用工厂模式获取,具体的构建对象的实现延迟到子类中。
      •      /**
              * 抽象类
            **/
            public abstract class AbstractClass
            {
                // 原语操作,放到子类去实现
                public abstract void PrimitiveOperation1();
                public abstract void PrimitiveOperation2();
        
                 // 模板方法,定义逻辑的骨架。
                public void TemplateMethod()
                {
                    PrimitiveOperation1();
                    PrimitiveOperation2();
        match(); }
          
        // 具体的操作
        public void match()
           {
        // 公共的实现
        }
                // 工厂模式:创建某个对象,这里用Object代替
                public abstract Object createObject();
        }
        /** * 具体类,实现了抽象类中的原语步骤 **/ public class ConcreteClass extends AbstractClass {
           @Override
        public void PrimitiveOperation1() { //具体实现 }
        @Override
        public void PrimitiveOperation2() { //具体实现 }

        // 钩子操作
        @Override
           public void match()
           {
        // 子类的实现
        }
        }

java的回调与模板方法

  • 定义

    模板方法:在于让其他类来扩展或具体实现在模板(父类)中固定的算法骨架中的某些算法步骤。在标准的模板方法实现中,主要使用继承的方式,使父类在运行期间可以调用到子类中。

    在java开发中,还有另一个方法可以实现同样的功能------java回调:通过回调在接口中定义的方法,调用到具体的实现类中的方法。在这种实现中,可以不写子类,而是使用匿名内部类来实现回调方法。
  • 结构
    • 回调接口:把所有需要扩展的方法定义出来。
    • 模板类:
      • 不再是抽象类,所有抽象方法删除。
      • 模板方法,添加一个参数,传入回调接口。
      • 在模板方法实现中,除了模板中固定的实现外,所有可以被扩展的方法,都应通过回调接口进行调用。
    • 客户端:需要使用匿名内部类来实现回调接口,并实现其中想要扩展的方法。
               /**
                * 回调接口
              **/
              public interface InterfaceCallback
              {
                  // 需要扩展的方法
                  public void PrimitiveOperation1();
                  public void PrimitiveOperation2();
           
                  // 工厂模式:创建某个对象,这里用Object代替
                  public Object createObject();
      
              }
      
               /**
                * 模板类
              **/
              public class TemplateClass
              {
                  // 模板方法,添加回调接口的入参。
                  public void TemplateMethod(InterfaceCallback callback)
                  {
                      callback.PrimitiveOperation1();
                      callback.PrimitiveOperation2();
                      match();
                  }
           
                  // 具体的操作
                  public void match()
                { 
                     // 实现
                  }
              }
      
               /**
                * 客户端
              **/
              public class Client
              {
                  // 测试模板方法。
                  public void TestTemplateMethod()
                  {
                      TemplateClass template = new TemplateClass();
                      template.TemplateMethod(new InterfaceCallback(){
                          
                          public void PrimitiveOperation1(){
                               //具体实现
                          }
                          
                          public void PrimitiveOperation2(){
                              //具体实现
                          }
                       
                          public Object createObject(){
                              //具体实现
                          }
                      });
                  }
              }                            
              

       

模板方法实现方式:继承/回调 总结

  • 回调方式更灵活,因为java是单继承,使用继承方式,子类就不能继承其他对象,而回调基于接口。
  • 继承方式,抽象方法和实现的类的关系是在编译时期静态决定的,是类级关系;回调方式,是在运行期间动态决定的,是对象级关系。
  • 继承方式更简单点,因为父类提供实现方法,子类不想扩展,不用管;回调方式,回调的接口需要将扩展的所有方法都定义进去,则,实现时,不管扩不扩展,都得实现。

模板方法优缺点

  • 优点是实现代码复用:把子类的公共功能提取到模板中实现。
  • 缺点是算法骨架不容易升级:模板和子类是非常耦合的,如果变更算法骨架,则相应的子类也可能相应的变化,所以抽取算法骨架,尽量确定不会变化的部分才放到模板中。

 

posted on 2017-11-17 16:21  婵婵  阅读(119)  评论(0编辑  收藏  举报

导航