关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

深入浅出设计模式 - 模板方法模式

发布时间:2023-06-28 00:00:37
博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家 Java知识图谱点击链接:体系化学习Java(Java面试专题) 感兴趣的同学可以收藏关注下 ,不然下次找不到哟 1、什么是模板方法模式 模板方法模式(Template Method Pattern)是一种行为设计模式,它定义了一个算法的框架,将一些步骤的具体实现延迟到子类中,使得子类可以改变算法的某些特定步骤,而不改变算法的结构。 模板方法模式的核心思想是:定义一个抽象类,其中包含一个模板方法,该方法中定义了算法的骨架,然后将一些步骤的实现交给子类去完成。子类可以重写这些步骤,从而改变算法的具体实现,但是算法的结构不会改变。 2、模板方法模式的优缺点 模板方法模式的优点包括: 将算法的骨架和具体实现分离,提高了代码的复用性和可维护性。 子类可以灵活地改变算法的某些步骤,从而实现不同的功能。 父类可以控制子类的执行顺序,保证算法的正确性。 模板方法模式的缺点包括: 父类和子类之间的耦合度较高,一旦父类的代码发生改变,可能会影响到子类的实现。 可能会导致类的数量增加,增加代码的复杂度。 3、模板方法模式的应用场景 模板方法模式适用于以下场景: 算法的整体步骤固定,但某些步骤的具体实现可以在子类中改变。 避免代码重复,将相同的代码抽象到父类中,子类只需要实现特定的代码即可。 父类需要控制子类的执行顺序,从而保证算法的正确性。 具体的应用场景有: 框架设计:框架中通常都会定义一些模板方法,子类通过实现特定的方法来完成框架的功能。 数据库访问:在访问数据库时,通常都需要进行连接、查询、关闭等操作,这些操作的顺序是固定的,但是具体的实现可以有所不同。 网络编程:在网络编程中,通常需要先建立连接、发送数据、接收数据等操作,这些操作的顺序是固定的,但是具体的实现可以有所不同。 面向对象设计:在面向对象设计中,通常会使用模板方法模式来实现一些通用的算法,如排序算法、搜索算法等。 游戏开发:在游戏开发中,通常需要实现一些通用的功能,如角色移动、攻击、防御等,这些功能的实现可以使用模板方法模式。 4、模板方法模式的结构 模板方法模式是一种行为设计模式,它定义了一个算法的骨架,并允许子类为一个或多个步骤提供实现。这种模式属于行为型模式。 模板方法模式的结构包括以下几个部分: 抽象类(AbstractClass):定义了算法的骨架,包含了若干个抽象方法,这些方法由子类实现。 具体类(ConcreteClass):实现了抽象类中定义的抽象方法,完成算法中的具体步骤。 钩子方法(Hook Method):在抽象类中定义的方法,子类可以选择性地覆盖它们,以改变算法的行为。 模板方法(Template Method):定义了算法的骨架,包含了一系列调用抽象方法和钩子方法的步骤,子类不能修改它的行为。 模板方法模式的核心思想是将算法的具体实现交给子类来完成,从而实现代码的复用和扩展。 5、模板方法模式的代码案例 package com.pany.camp.design.principle.template; /** * * @description: 抽象类 * @copyright: @Copyright (c) 2022 * @company: Aiocloud * @author: pany * @version: 1.0.0 * @createTime: 2023-06-27 22:42 */ public abstract class CaffeineBeverage { final void prepareRecipe() { boilWater(); brew(); pourInCup(); if (customerWantsCondiments()) { addCondiments(); } } void boilWater() { System.out.println("Boiling water"); } void pourInCup() { System.out.println("Pouring into cup"); } abstract void brew(); abstract void addCondiments(); boolean customerWantsCondiments() { return true; } } package com.pany.camp.design.principle.template; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * @description: 咖啡 * @copyright: @Copyright (c) 2022 * @company: Aiocloud * @author: pany * @version: 1.0.0 * @createTime: 2023-06-27 22:42 */ class Coffee extends CaffeineBeverage { void brew() { System.out.println("Dripping coffee through filter"); } void addCondiments() { System.out.println("Adding sugar and milk"); } boolean customerWantsCondiments() { String answer = getUserInput(); return answer.toLowerCase().startsWith("y"); } private String getUserInput() { String answer = null; System.out.print("Would you like sugar and milk with your coffee? (y/n) "); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); try { answer = in.readLine(); } catch (IOException e) { System.err.println("IO error trying to read your answer"); } if (answer == null) { return "no"; } return answer; } } package com.pany.camp.design.principle.template; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * @description: 茶 * @copyright: @Copyright (c) 2022 * @company: Aiocloud * @author: pany * @version: 1.0.0 * @createTime: 2023-06-27 22:43 */ class Tea extends CaffeineBeverage { void brew() { System.out.println("Steeping the tea"); } void addCondiments() { System.out.println("Adding lemon"); } boolean customerWantsCondiments() { String answer = getUserInput(); return answer.toLowerCase().startsWith("y"); } private String getUserInput() { String answer = null; System.out.print("Would you like lemon with your tea? (y/n) "); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); try { answer = in.readLine(); } catch (IOException e) { System.err.println("IO error trying to read your answer"); } if (answer == null) { return "no"; } return answer; } } package com.pany.camp.design.principle.template; /** * * @description: 客户端 * @copyright: @Copyright (c) 2022 * @company: Aiocloud * @author: pany * @version: 1.0.0 * @createTime: 2023-06-27 22:43 */ public class Client { public static void main(String[] args) { CaffeineBeverage coffee = new Coffee(); CaffeineBeverage tea = new Tea(); System.out.println("Making coffee..."); coffee.prepareRecipe(); System.out.println("\nMaking tea..."); tea.prepareRecipe(); } } CaffeineBeverage 是抽象类,定义了制作咖啡因饮料的模板方法 prepareRecipe() ,以及一些基本方法 boilWater() 和 pourInCup() 。 CaffeineBeverage 还定义了两个抽象方法 brew() 和 addCondiments() ,由子类实现。 Coffee 和 Tea 是具体类,实现了 brew() 和 addCondiments() 方法,以及 customerWantsCondiments() 钩子方法,可以根据客户的需求选择是否添加调料。 在 main 函数中,我们创建了 Coffee 和 Tea 对象,并调用它们的 prepareRecipe() 方法,输出了制作咖啡和茶的过程。 输出结果如下: Making coffee... Boiling water Dripping coffee through filter Pouring into cup Would you like sugar and milk with your coffee? (y/n) y Adding sugar and milk Making tea... Boiling water Steeping the tea Pouring into cup Would you like lemon with your tea? (y/n) y Adding lemon Process finished with exit code 0 本文由激流原创,首发于CSDN博客,博客主页 https://blog.csdn.net/qq_37967783?spm=1010.2135.3001.5421喜欢的话记得点赞收藏啊

/template/Home/leiyu/PC/Static