设计模式之模板方法

1、定义

模板方法设计模式(Template Method Design Pattern)是一种行为型设计模式它定义了一个操作中的算法的骨架,而且将一些步骤延迟到子类中。它使得子类可以改变算法的某些特定步骤,而同时还不改变该算法的结构。具体地说,模板方法定义了一个算法的高层结构,而将具体实现交给子类去完成。

模板方法设计模式包含以下几个角色:

  1. 抽象类(Abstract Class):定义了一个模板方法,它给出了算法的基本骨架,其中包含若干个步骤,这些步骤的具体实现由子类去完成。
  2. 具体实现子类(Concrete Class):实现抽象类中的抽象方法,在抽象类中完成的步骤中填入不同的具体实现,以完成算法的不同变体。

2、实现

在实际的应用中,模板方法设计模式常用于将一些公共的算法步骤提取出来,避免代码冗余和耦合性过高,同时也可以灵活地组合和拓展算法的不同实现。

下面是一个简单的模板方法设计模式示例代码:

public abstract class AbstractClass {
    /* 模板方法 */
    public final void templateMethod() {
        method1();
        method2();
        method3();
    }

    /* 抽象方法1 */
    public abstract void method1();

    /* 抽象方法2 */
    public abstract void method2();

    /* 具体方法3 */
    public void method3() {
        System.out.println("AbstractClass.method3() is called.");
    }
}

public class ConcreteClass extends AbstractClass {
    /* 实现抽象方法1 */
    @Override
    public void method1() {
        System.out.println("ConcreteClass.method1() is called.");
    }

    /* 实现抽象方法2 */
    @Override
    public void method2() {
        System.out.println("ConcreteClass.method2() is called.");
    }
}

public class Client {
    public static void main(String[] args) {
        AbstractClass abstractClass = new ConcreteClass();
        abstractClass.templateMethod();
    }
}

在上面的示例代码中,AbstractClass为抽象类,定义了一个模板方法templateMethod(),其中包含三个步骤方法:method1()、method2()、method3()。其中method3()为具体方法,而method1()和method2()则为抽象方法,需要具体实现类去完成。

ConcreteClass为具体实现子类,实现了抽象类中的method1()和method2()方法,在抽象类中完成的步骤中填入了具体的实现。

在Client的main方法中,先创建了ConcreteClass对象,再通过该对象调用AbstractClass中定义的模板方法templateMethod(),从而完成了算法的整个流程。在调用模板方法的过程中,先调用了method1()和method2()两个抽象方法,最后调用了具体方法method3()。

3、应用场景

模板方法设计模式常用于以下情况:

  1. 算法设计:当多个算法或操作具有相同的基本流程和操作步骤,但其具体实现方式各不相同时,可以将这些相同的基本流程和操作步骤提取到一个模板方法中,然后将具体实现延迟到其子类中去完成。

  2. 复杂实现:当一个方法或操作具有多个步骤、流程或判断逻辑时,可以将其拆分成多个较小的模块,使用模板方法将这些模块组合起来,让代码更易于理解和维护。

  3. 框架设计:在框架设计中,通常会定义一些基本的操作流程和约束,而具体的业务逻辑则交由使用者来实现。这时,可以利用模板方法设计模式降低使用者的编码难度。

以下是几个实际应用场景:

  1. 框架设计中,如使用Spring框架时,可以借助Spring提供的模板方法来减轻编程难度,如JdbcTemplate、JmsTemplate、HibernateTemplate等。
  2. 在游戏开发中,可以使用模板方法来设计游戏关卡、任务流程和角色AI等系统。
  3. 在Web开发中,可以使用模板方法来处理请求、响应和控制页面流程和表单验证等系统。
public abstract class AbstractWebController {
    /* 模板方法 */
    public void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        // 验证表单数据合法性
        if (validateFormData(request, response)) {
            // 处理请求并返回响应
            handleRequest(request, response);
        } else {
            // 验证失败则重定向到错误页面
            response.sendRedirect("/error.jsp");
        }
    }

    /* 验证表单数据的合法性 */
    protected abstract boolean validateFormData(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException;

    /* 处理请求并返回响应 */
    protected abstract void handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException;
}

public class ConcreteWebController extends AbstractWebController {
    /* 实现表单数据验证 */
    @Override
    protected boolean validateFormData(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        // 省略具体实现
        return true;
    }

    /* 处理请求并返回响应 */
    @Override
    protected void handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        // 省略具体实现
        response.sendRedirect("/success.jsp");
    }
}

public class Client {
    public static void main(String[] args) {
        HttpServletRequest request = null;
        HttpServletResponse response = null;
        AbstractWebController controller = new ConcreteWebController();
        try {
            controller.processRequest(request, response);
        } catch (IOException | ServletException e) {
            e.printStackTrace();
        }
    }
}

在上面的代码示例中,AbstractWebController为抽象类,定义了一个模板方法processRequest(),其中包含两个步骤方法:validateFormData()和handleRequest()。其中validateFormData()为抽象方法,需要具体实现类去完成。handleRequest()为具体方法,处理请求并返回响应。

ConcreteWebController为具体实现子类,实现了抽象类中的validateFormData()和handleRequest()方法,在抽象类中完成的步骤中填入了具体的实现。

在Client的main方法中,先创建了一个ConcreteWebController对象,再通过该对象调用AbstractWebController中定义的模板方法processRequest(),从而完成了请求处理过程。

在具体实现中,可以根据不同的请求和响应需要进行不同的操作,例如验证表单数据合法性、处理请求并返回响应等。由于模板方法processRequest()中定义的流程是固定的,所以无需重复编写相似的代码,可以提高开发效率和代码复用性。

总结:模板方法设计模式可以将相同算法的不变部分放到抽象类中,而将可变的部分放到子类中,通过约束子类的行为来提高代码的复用性和可扩展性。它是一种行为型设计模式,应用广泛,具有简单易懂、结构清晰和代码可维护性高等优点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
模板方法设计模式是一种行为设计模式,它定义了一个算法的骨架,将一些步骤的实现延迟到子类中。这种模式可以确保算法的结构保持不变,但允许子类提供特定的实现细节。在C++中,模板方法设计模式可以通过使用虚函数和继承来实现。 在给出的引用中,我们可以看到一个名为CoffeineBeverage的类,它定义了一个prepare_recipe()方法,并在内部调用了其他几个私有方法。这个类是一个基类,可以被子类继承并重写其中的方法。 具体来说,模板方法设计模式的关键是将算法的骨架定义在基类中,而将可变的实现细节留给子类去实现。在这个例子中,prepare_recipe()方法是算法的骨架,而brew()和add_condiments()方法则是可变的实现细节。 通过将brew()和add_condiments()方法定义为虚函数,基类CoffeineBeverage允许子类去重写这些方法以提供自己的实现。这样,当调用prepare_recipe()方法时,实际执行的是子类中重写后的方法。 使用模板方法设计模式的好处是可以提高代码的复用性和可扩展性。算法的骨架在基类中只需要定义一次,而具体的实现细节可以在不同的子类中灵活变化。 总结起来,C++中的模板方法设计模式通过定义一个算法的骨架并将可变的实现细节留给子类去实现,可以提供代码的复用性和可扩展性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [C++设计模式模板方法模式](https://blog.csdn.net/Long_xu/article/details/127118813)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [C++设计模式-模板方法模式](https://blog.csdn.net/qq78442761/article/details/91990149)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值