我们应该在哪里使用模板方法 - 模式?

use*_*312 8 design-patterns template-method-pattern

任何人都可以让我知道应该使用模板方法 - 模式的一些示例情况吗?

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

(到目前为止,我发现它仅用于映射DA层中的数据.抱歉!!!)

Pas*_*ent 8

模板方法图案提供了一种用于执行任何排序算法或操作的骨架,并且它允许所述子类的逻辑的重新定义的一部分.

优点:自然适合构建框架,因此父框架类可以回调到子实现的方法.

例子:

缺点:在Java中将您限制为单个继承.

  • 我刚刚查看了 AbstractList 和 HttpServlet 类。我在其中没有看到任何“模板方法”。我怀疑您将模板方法模式与简单的“控制反转”用法混淆了。该模式不是关于拥有一个其方法由框架调用的基类,而是关于拥有一个封装算法的方法,该算法可以由覆盖特殊扩展点的子类(从模板方法调用的基类的可覆盖方法,它本身并不意味着被覆盖)。 (2认同)
  • 您说“子类确实实现了 get、size、set、remove”:true,因为 AbstractList 只是部分实现 - 除了在 AbstractList 本身中完全实现的 `size` 方法。显然,您必须了解模板方法是在基类中实现的,而不是在子类中覆盖;只有从模板方法调用的“原始操作”在子类中实现。例如,`AbstractList#get(int)` 方法是抽象的,因此只能是“原始操作”(您同意,对吗?)。但是这个类中没有模板方法。 (2认同)

Rog*_*rio 6

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

  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 Event Dispatch Thread)中在处理期间和结束时调用,以允许更新UI.

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

最后,我必须说,虽然这肯定是一种有用的设计模式,但并不是经常会出现真正适用的情况.简单地让一个基类具有在子类中被覆盖的方法(根据我的经验,更常见的情况)本身并不足以作为模式的应用程序.


MMK*_*ami 5

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

\n\n
    \n
  • 当你希望你的程序是“Open For Extension\xe2\x80\x9d 并且\xe2\x80\x9cClosed for Modification\xe2\x80\x9d”时。这意味着模块的行为可以扩展,这样我们就可以随着应用程序需求的变化,或者为了满足新应用程序的需要,模块会以新的和不同的方式表现出来。但是,这样的模块的源代码是不可侵犯的。任何人都不允许对其源代码进行更改。下面的示例中,您可以添加新的工资计算方式(例如Remotely class),而无需更改之前的代码。

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

  • \n
\n\n

函数 0: 函数 1: ... 函数 N:

\n\n
1       1               1\n2       2               2\n...     ...             ...\n5       6               n\n3       3               3\n4       4               4\n...     ...             ...\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

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

    \n\n
    public abstract class HttpServlet extends GenericServlet \n    implements java.io.Serializable  {\n    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {\n        ...\n    }\n\nprotected void service(HttpServletRequest req, HttpServletResponse resp)\n    throws ServletException, IOException {\n        ....\n        doGet(req, resp);\n        ...\n    }\n    ...\n}\n}\n\npublic class MyServlet extends HttpServlet {\n\n    protected void doGet(HttpServletRequest request, HttpServletResponse response)\n        throws ServletException, IOException {\n\n            //do something\n        ...\n    }\n    ...\n}\n
    Run Code Online (Sandbox Code Playgroud)
  • \n
\n