谁能告诉我一些应该使用模板方法 - 模式的示例情况?

根据您自己的经验,给我一些实际用途。

(到目前为止,我发现它仅对于映射 DA 层中的数据有用。对不起!!!)

有帮助吗?

解决方案

我试图为您提供一些现实世界的示例,以及一些应使用模板方法模式的常见情况。

  • 当您希望您的程序“开放进行扩展”并且“关闭进行修改”时。 这意味着模块的行为可以扩展,这样我们就可以随着应用程序需求的变化使模块以新的、不同的方式运行,或者满足新应用程序的需求。然而,这样的模块的源代码是不可侵犯的。任何人都不得对其源代码进行更改。在下面的示例中,您可以添加新的工资计算方式(例如Remotely class),而无需更改以前的代码。

    public abstract class Salary {
    
       public final void calculate() {
            System.out.println("First shared tasks is done.");
            getBaseSalary();
            System.out.println("Second shared tasks is done.");
       }
    
       public abstract void getBaseSalary();
    
    }
    
    public class Hourly extends Salary {
    
        @Override
        public void getBaseSalary() {
            System.out.println("Special Task is done.");
        }
    
    }
    
    public class Test {
    
        public static void main(String[] args) {
            Salary salary = ....
            salary.calculate();
        }
    }
    
  • 当您面对许多相同的代码行时,这些代码通过延迟算法的某些步骤而重复。 当您实现方法或函数的内容时,您会发现代码的某些部分因一种类型而异。这些部分的特点是可以重新定义或修改方法或函数的这些部分,而不改变算法(方法或函数)的主要结构。例如,如果您想在没有此模式的情况下解决此问题,您将面临以下示例:

函数0:功能1:...函数N:

1       1               1
2       2               2
...     ...             ...
5       6               n
3       3               3
4       4               4
...     ...             ...

正如您所看到的,第 5、6、n 节的代码在一个函数和另一个函数之间是不同的,但是您共享了重复的节,例如 1、2、3、4。让我们考虑使用著名的 java 库之一的解决方案。

public abstract class InputStream implements Closeable {

    public abstract int read() throws IOException;

    public int read(byte b[], int off, int len) throws IOException {
        ....

        int c = read();
        ....
    }

    ....

}

public class ByteArrayInputStream extends InputStream {  

    ...

    public synchronized int read() {
        return (pos < count) ? (buf[pos++] & 0xff) : -1;
        }
    ...
}
  • 当您作为框架的设计者时,希望您的客户端仅使用作为参数传递给框架的任何可执行代码,框架预计会在给定时间回调(执行)该参数。 此执行可能是立即执行(如在同步回调中​​),也可能稍后发生(如在异步回调中)。让我们考虑一下著名的之一。

    public abstract class HttpServlet extends GenericServlet 
        implements java.io.Serializable  {
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
            ...
        }
    
    protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
            ....
            doGet(req, resp);
            ...
        }
        ...
    }
    }
    
    public class MyServlet extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    
                //do something
            ...
        }
        ...
    }
    

其他提示

A 模板方法模式 提供执行任何类型的算法或操作的骨架,并且它允许子类重新定义部分逻辑。

优点:自然适合构建框架,以便父框架类可以回调子框架中实现的方法。

例子:

  • java.util.AbstractList
  • Servlet 的 doGet 和 doPost 方法
  • MDB 的 onMessage 方法
  • Struts 动作类
  • Spring的数据访问类

缺点:将您限制为 Java 中的单一继承。

的一个应用 模板法 模式有两个主要特征:

  1. 有一个基类(在 Java 中,只有一个 protected 构造函数和可选声明为 abstract) 它将在客户端代码中进行子类化。
  2. 两组方法 基类中定义:a) 一个或多个 模板方法 (通常只有一个)和一个或多个 原始操作 方法(通常不止一种)。每个模板方法都代表一个高级操作,在基类本身中按照原语操作实现,这些操作意味着在每个特定子类中实现/重写。通常,模板方法是公共的且不可重写的(final, ,在 Java 中);它的API文档必须准确指定它调用哪些原始操作方法以及何时调用(即它必须描述“算法”)。代表算法中的一个步骤的原始操作方法应该是非公开的但可重写的(protected, ,在 Java 中),并且可以有两种类型:a) 一个抽象方法 必须 在子类中实现;b) 具有默认/空实现的方法 可能 在子类中被覆盖。

Java 6 SDK 中的一个很好的例子是 execute() 的方法 javax.swing.SwingWorker 类(它是一个 public final void 方法)。在这种情况下,原始的操作方法是 doInBackground(), process(List), , 和 done(). 。第一个是抽象的,因此需要在子类中实现;它由后台线程中的模板方法调用。另外两个具有空实现,可以选择在子类中重写;它们分别在处理过程中和处理结束时在 EDT(Swing 事件调度线程)中调用,以允许更新 UI。

根据我自己的经验,我有时会使用这种模式。其中一个例子是 Java 基类实现了 java.util.Iterator 接口,其中 next() 是模板方法,并且只有一个原始操作方法负责实例化特定的域实体类(这意味着在使用 JDBC 迭代持久域实体对象列表时使用)。同一应用程序中的一个更好的例子是一个基类,其中模板方法实现了一个多步骤算法,旨在从给定的持久实体列表填充“业务实体维护屏幕”(使用 Swing);调用原始操作方法来 1) 清除当前屏幕状态,2) 在屏幕内的表视图中添加实体;如果屏幕可编辑,则可以选择从模板方法调用其他原始操作。

最后,我必须说,虽然这确实是一种有用的设计模式,但真正适用的情况并不常见。仅仅拥有一个带有在子类中重写的方法的基类(根据我的经验,这是一种更常见的情况)本身并不足以成为该模式的应用程序。

在模板的方法,最重要的是,你必须定义一系列的抽象方法的步骤或算法,让子类替代与这些方法的具体实施。

我在文档生成程序的一个应用。

public abstract DocumentGenerator() 
{
   generateHeader();
   generateBody();
   generateDetails();
}
public HTMLDocGenerator : DocumentGenerator()
{
   public override generateBody()
   {
     //generate as in html format
   }
}

可以具有不同的实现,如PDF发生器CSV发生器和这里的值被他们comform到算法(产生 - >标题,正文,详细信息)。

当存在与许多实现的算法,应使用的模板图案。该算法在基类的一个函数来定义和实现是由基类和子类来完成。具有实时例子详细说明在 http://preciselyconcise.com/design_patterns/templatemethod.php给出

我将绘制一个真实的例子,其中利用我一些模板的方法。

在一个C ++计算机视觉算法的应用算法的行为被设计为呈现出几个基于根据塞进在启动时加载配置文件的枚举在运行时读取某些选项的算法行为香料。该算法的整体框架,不同的是在原本经的代码相同的部分将被残酷重复刚才的那一级调用不同功能的中间塞上一些关键回调相同。这些回调我想用被抽象成模板方法基类和模板方法模式防止所有的代码重复。我们使用的枚举基本上决定什么子类实例化我我的基类指针指向,因此放贷算法及其相关的味道位的行为。

现在一些背后的各种运行算法的口味的动机之一是在线VS软件的离线功能,控制我们的仪器。离线风味很拽更丰富的调试/诊断输出,并保持局部坐标系的一些图像像素,而网上的味道把每一件事情在绝对坐标空间,并保持特定于和它的所有机器人的运行状态的仪器并没有什么顾虑。另一个枚举开一组,我们使用一些机器学习,以及因为不同的分类分别在不同的组,通过代码的机构另有流相同数据的受过训练的,但需要以不同的方式解释一些管理条件如何根据分类中选择该数据已创建。

我相信这种情况下,使用我发生起了所谓的的孔在中间问题。

我已经使用业务逻辑模板的方法,其中多个组件共享相同的过程,但实施略有不同。

  

在模板方法定义的算法的骨架结构,但   推迟某些步骤和细节的子类。结构和   该算法的流程保持不变,但是步骤的细节   推迟到子类。

我用模板方法模式准备文档内容。有许多不同种类的每一种类型都有自己的小的修改文件。然而,文件编制的主要过程是相同的所有。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top