`
xyheqhd888
  • 浏览: 409246 次
  • 性别: Icon_minigender_1
  • 来自: 秦皇岛
社区版块
存档分类
最新评论

Template Method二

阅读更多

   Template Method模式类似于Adapter模式,原因在于两种模式都允许开发者简化和指定其他开发者程序代码完成设计的方式。在Adapter模式中,一个开发者也许指定设计所需的对象的接口。第二个开发者会创建一个对象,提供设计所期望的接口,但是使用具有其他接口的已有类的服务。在Template Method模式中,一个开发者也许提供一个通用算法,而第二个开发者提供该算法的关键步骤。

    

     Aster公司的火药球填压机接受空的金属模具,然后将火药球压入模具里面。该机器有若干个料斗(hopper),各种化学品在料斗中被配制成药糊,随后,这些药糊被压入模具中。当机器关闭时,处理区中的模具将不再被处理,输入传送带上的所有模具都将经由处理区到达输出传送带,但不再处理这些模具。然后机器倒空当前剩余的药糊,并用水清洗处理区。填压机根据板载计算机发出的指令有条不紊地完成了上述工作。示意图如下:

 
                                           

图2 Aster火药球填压机提供输入输出传送带来移动火药球模具。

Ooninoz公司添加一个回收传送带,用于回收被倒空的药糊



  

Aster公司的火药球填压机提供一个抽象类,在Oozinoz系统中我们必须为其提供一个子类才能使填压机运转

 

 Aster火药球填压机具有一定的智能,并能能够独立工作。其开发人员已经考虑到填压机可能用于智能化的工厂里,并且可能需要与其他设备通信。例如,如果正在处理的模具尚未处理完毕,那么shutDown()方法将会通知工厂:

public void shutdown()
{
    if(inProcess()){
        stopProcessing();
        maskMoldIncomplete(currentMoldID);
    }

    usherInputMolds();
    dischargePaste();
    flush();
}

 markMoldIncomplete()方法和AsterStarPress类都是抽象的。在Oozinoz公司的系统中,我们需要为其创建一个子类,并实现其中所需的方法,然后将该代码下载到火药球填压机的板载计算机上。在markMoldIncomplete()方法的实现中,我们将把未完成的模具信息传送给MaterialManager单例,从而实现对原料状态的跟踪。

 

突破题:请实现OzAsterStarPress类的markMoldIncomplete()方法。

答:在markMoldIncomplete()方法体内,一个没有处理完毕的模具信息被传给了原材料管理器,具体代码如下:

 
public class OzAsterStarPress extends AsterStarPress
{
    public void markMoldIncomplete(int id){
         MaterialManager.getManager().setMoldIncomplete(id);
    }
}

Aster火药球填压机的开发人员清楚地知道焰火工厂的生产流程,因此他们已经在填压机上提供了与其他工厂设备进行通信的支持。虽然如此,还有可能存在某些地方是Aster的开发人员所没有预见到的,这个时候就需要我们自己来实现填压机与其他设备的通信。

 

3. 模式钩子

  钩子就是一个方法调用。开发人员可以将它放到自己代码中的特定位置,这样其他开发人员便可以在该位置插入他们自己的代码。当我们希望适配其他开发人员的代码的时候,或者当我们需要在其他人的代码中插入自己的控制的时候,就可以使用钩子。其他开发人员如果愿意帮忙的话,通常会允许我们在他们代码的适当地方插入一个方法调用。开发人员通常会为自己代码中的钩子提供一个存根实现,这样,不需要使用钩子的其他用户就不必重写这个钩子方法。

  下面再考虑前面Aster公司压缩机的例子。当机器关闭时,Aster火药球填压机将倒空化学品药糊,并用水清洗处理区。填压机必须倒空该药糊,以防止药糊干燥后堵塞机器。在火药球填压机倒空药糊后,我们可以安排一个机器人将药糊转移到另外一个传送带上。现在的问题是,我们期望在shutdown()方法的两个语句间获得对系统的控制权:

 
dischargePaste();
flush();

我们可能会在代码中调用收集药糊的方法,从而重写dischargePaste():

 
public void dischargePaste()
{
     super.dischargePaste();
     getFactory().collectPaste();
}

 该方法在清空药糊后有效地插入一个步骤。所添加的步骤使用一个Factory单例收集火药球填压机倒空的药糊。当执行shutdown()方法时,工厂机器人会在shutdown()方法用水清洗处理区之前搜集废弃的药糊。不幸的是,dischargePaste()方法代码非常危险,因为药糊的收集工作是在排空药糊的方法中附带完成的。Aster的开发人员一定不会知道你会有这种方式来定义dischargePaste()方法。如果他们修改代码,在你不想收集药糊的时候倒空药糊,这将是一个错误。

    开发人员通常都是通过努力的修改代码来解决问题。但是,这里的难点在于开发人员要通过与其他开发人员沟通来解决这个问题。

 

自我突破题:请通知Aster的开发人员,要求他们做一些改变,让我们能够在机器冲洗处理区之前安全地悼收集被倒空的药糊。

答:可能会这样陈述请求:我希望你能够在shutDown()方法中增加一个调用,该调用在机器排空药糊之后和机器开始注水之前执行。如果将这个方法称为collectPaste(),那么我们可以在该方法中保存药糊,从而使得药糊可以被Oozinoz公司重复利用。

      开发人员很可能会与你协商从而确定这个方法的名称。名称并不重要,重要是通过在一个模板方法中请求一个钩子,可以解决现有代码存在的问题,并使我们的代码更加健壮。

 

    在Template Method模式中,我们可以利用子类提供的步骤来完成某个算法,这个步骤可以是一个可选的步骤,并且能够根据其他开发人员的需要挂到子类的代码中。尽管该模式的目的是使用一个单独的类来定义算法的一部分,但是,当我们需要对出现在多个方法中的算法进行重构的时候,也可以使用Template Method模式。

 

4.重构为Template Method模式

  在应用Template Method模式的时候,层次结构中的类通常会使用我们或者其他人在一个抽象的超类中提供的算法框架。当我们在多个方法中实现类似的算法时,也可以重构为Template Method模式(重构是使用更好的设计思路重新实现等价功能的过程)。下面我们再看看 工厂方法模式 中的Machine和MachinePlanner层次结构。如下图4所示,Machine类将createPlanner()方法作为Factory Method模式,该方法返回了MachinePlanner层次结构中的一个适当的子类。

 

 

 

 

 

                                   一个Machine对象能够为自己创建一个适当的MachinePlanenr实例

 

当要求创建一个规划器时,Machine类的两个子类会实例化MachinePlanner类层次结构中指定的子类。这些类---ShellAssembler和StarePress---存在相同的问题,因为它们希望只在需要时创建MachinePlanner。

   查看这些类的代码,我们注意到子类使用了类似于滞后初始化规划器这样的技术。比如ShellAssembler类包含getPlanner()方法,滞后实例化planner成员:

 
public ShellPlanner getPlanner()
{
     if(planner == null)
        planner = new ShellPlanner(this);
     return planner;
}

StarPress类的getPlanner()方法也对planner属性进行滞后初始化:

public StarPressPlanner getPlanner()
{
     if(planner == null)
        planner = new StarPressPlanner(this);
     return planner;
}

 

 

  Machine类的其他子类也使用了类似的技术,仅在第一次使用时才创建规划器(planner)对象。这样就需要重构代码,需要清理和缩减维护的代码量。假设你决定给Machine类提供一个类型为MachinePlanner的planner属性,需要从子类中删除这个属性,并删除已有的getPlanner()方法。

 

 

突破题:请写出Machine类中getPlanner()方法的实现代码:

答:Machine类的getPlanner()方法充分利用了抽象的createPlanner()方法。具体代码如下:

public MachinePlanner getPlanner()
{
      if(planner == null)
         planner = createPlanner();
      return planner;
}

 这部分代码要求你往Machine类中增加planner字段。在往Machine类中加入这个属性和getPlanner()方法之后,我们可以删掉Machine子类中的这个属性和这个方法。

 这种重构可以创建Template Method模式的一个实例。getPlanner()方法对规划器变量进行了滞后初始化,而初始化过程使用子类提供的createPlanner()方法。

 

 

 

 

    我们可以把自己的代码重构为Template Method模式的实例,具体的做法是:将类似方法的框架抽象出来,并将方法框架上移到超类中,而子类只需提供在算法的实现过程中不同的那些步骤。

 

5.小结

   Template Method模式的目的在于在一个方法中定义一个算法,并对算法的某些步骤进行抽象,这样,我们可以将这些步骤的具体实现从这个方法中提出,并在其外部方法中定义这些步骤,或者是用一个接口定义这些步骤,留待其他类来提供这些步骤的实现。

   Template Method模式通常可以作为开发人员之间的某种约束。一个开发人员提供算法的框架,另一个开发人员则提供算法某些步骤的具体实现。这也许是需要算法实现的步骤,或者是算法的开发人员在算法中某一位置设置的钩子。

   Template Method模式并不要求我们必须在定义子类前编写模板方法。我们可能在已有的类层次结构中发现相似的方法。在这种情况下,我们可以抽象出算法的框架,并把它上移到超类中,从而应用Template Method模式来简化和组织代码。

分享到:
评论

相关推荐

    TemplateMethod.rar

    标题“TemplateMethod.rar”暗示了这个压缩包包含的是关于Qt平台上实现模板方法设计模式的示例代码。Qt是一个跨平台的应用程序开发框架,常用于创建GUI程序,但也可用于非图形化的后台服务。 描述中的“模板方法...

    TemplateMethod.zip

    在这个例子中,`AbstractClass`是抽象基类,它定义了模板方法`templateMethod`,并声明了两个抽象方法`primitiveOperation1`和`primitiveOperation2`。`ConcreteClass1`和`ConcreteClass2`是具体的子类,它们实现了...

    template-method-demo 模板方法示例

    在"template-method-demo"这个示例中,我们可以预见到它将展示如何在Java中应用模板方法模式。这个压缩包可能包含以下内容: 1. 一个抽象类(例如:`AbstractClass`),它定义了模板方法。在这个类中,可能会有一个...

    设计模式C++学习之模板方法模式(Template Method)

    在这个例子中,`AbstractClass`是模板类,定义了`templateMethod`模板方法,它调用了`primitiveOperation1`、`primitiveOperation2`以及组件(Component)的`operation`方法。`ConcreteComponentA`和`...

    20-Template Method.rar

    模板方法(Template Method)设计模式是一种行为型设计模式,它在面向对象编程中扮演着重要的角色。这个模式允许我们定义一个操作中的算法骨架,而将一些步骤延迟到子类中。这样,子类可以不改变一个算法的结构即可...

    TemplateMethod Pattern.unitypackage

    TemplateMethod Pattern.unitypackage是一个模板方法模式的小栗子。

    TemplateMethod 模式与代码重构

    TemplateMethod(模板方法)设计模式是一种行为设计模式,它在面向对象编程中扮演着重要的角色。这个模式允许我们在抽象类中定义一个算法的框架,同时允许子类在不改变算法结构的情况下重写算法中的特定步骤。通过...

    Head First 设计模式 (八) 模板方法模式(Template Method pattern) C++实现

    在这个例子中,`AbstractClass`定义了`templateMethod`模板方法,其中`step1()`是具体实现,而`step2()`和`step3()`作为抽象方法由`ConcreteClass1`和`ConcreteClass2`这两个具体类来实现。这样,不同的具体类可以...

    C++设计模式课件3_Template Method_模板方法.pdf

    ### C++设计模式课件3_Template Method_模板方法 #### 模板方法设计模式解析 模板方法模式(Template Method Pattern)是一种行为型设计模式,它允许我们定义算法的骨架,并将部分步骤推迟到子类中实现。这种模式...

    Discovering Template Method Pattern in Google Android framework

    模板方法模式(Template Method Pattern)在Google Android框架中的应用是一个重要的设计模式实例,它允许开发者定义一个算法骨架,而将一些步骤延迟到子类中。这个模式的关键在于它定义了一个操作中的算法步骤,并...

    C++设计模式代码资源3_Template Method_模板方法.zip

    "模板方法"(Template Method)是设计模式中的一个经典概念,它属于行为设计模式,主要用在父类中定义一个算法的框架,允许子类在这个框架内重定义特定的步骤。这个模式通常用于代码复用和保持代码结构的一致性。 ...

    C#中的TemplateMethod模式问题分析

    TemplateMethod模式是一种行为设计模式,它允许在定义算法框架的同时,允许子类为算法的特定步骤提供实现。这种模式在C#中广泛应用于创建可扩展的代码结构,使得父类可以控制算法的流程,而具体的操作则由子类来完成...

    .NET设计模式(16):模版方法(TemplateMethod)

    摘要:Template Method模式是比较简单的设计模式之一,但它却是代码复用的一项基本的技术,在类库中尤其重要。变化一直以来都是软件设计的永恒话题,在XP编程中提倡拥抱变化,积极应对。如何更好的去抓住变化点,...

    模板方法模式(TemplateMethod)原理图

    模板方法模式是一种行为设计模式,它在一个方法中定义算法的骨架,将一些步骤延迟到子类中实现。 具体来说,模板方法模式的关键特点包括: 抽象类:在抽象类中定义一个模板方法,该方法给出了算法的框架。...

    Template(模板模式)

    obj2->templateMethod(); delete obj1; delete obj2; return 0; } ``` 编译过程会产生`Template.o`和`main.o`对象文件,然后链接成可执行文件`a.out`。 模板模式的优势在于: 1. 封装变化:模板模式将不变的...

    【原创】Open close principle sample, state pattern, template method pattern

    在软件设计领域,设计模式是解决常见问题的可重用解决方案。它们是经过验证的、在特定上下文中高效的设计决策,被广泛应用于构建可维护和可扩展的软件系统。本篇将深入探讨“开闭原则”(Open Close Principle,OCP...

    C#模板方法模式(Template Method Pattern)实例教程

    2. **模板方法(Template Method)**:模板方法是抽象类中的一个方法,它定义了算法的主要结构,通常包括一系列步骤。在这个例子中,`MakeHongShaoRou()`就是模板方法,它调用了具体方法来执行红烧肉的制作流程。 3...

    C++设计模式编程中Template Method模板方法模式的运用

    void TemplateMethod() { PrimitiveOperation1(); PrimitiveOperation2(); } protected: virtual void PrimitiveOperation1() = 0; // 抽象方法 virtual void PrimitiveOperation2() = 0; // 抽象方法 ...

    C++设计模式笔记(03-01) – Template Method_模板方法(上)

    C++设计模式笔记(03-02) – Template Method_模板方法(下): https://blog.csdn.net/mofan6930/article/details/104383750 参考书籍:《设计模式:可复用面向对象软件的基础》 参考课程:《C++设计模式》-李建忠 ...

Global site tag (gtag.js) - Google Analytics