找回密码
 立即注册
首页 业界区 业界 【模板方法设计模式详解】C/Java/JS/Go/Python/TS不同语 ...

【模板方法设计模式详解】C/Java/JS/Go/Python/TS不同语言实现

阜逐忍 2025-6-6 09:47:41
简介

模板方法模式(Template Method Pattern)也叫模板模式,是一种行为型模式。它定义了一个抽象公开类,包含基本的算法骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构,只是重定义该算法的某些特定步骤。不同的子类以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。以此基于公共的模板,来实现实现不同的功能。
模板模式适用于一些复杂操作进行步骤分割、抽取公共部分由抽象父类实现、将不同的部分在父类中定义抽象实现、而将具体实现过程由子类完成。对于有多个子类具有共有的方法,且逻辑相同,可以考虑作为模板方法。
作用


  • 相同的部分父类给出统一的模板,子类大量复用,从而节省代码,复用逻辑。
  • 封装不变部分,扩展可变部分,行为由父类控制,子类灵活实现,便于维护和扩展。
实现步骤


  • 创建一个抽象的模板类,定义基本流程,同时定义一些基本方法供子类去实现。
  • 创建多个子类继承抽象模板,覆盖父类的相关动作和方法。
UML

 
template-pattern.pngJava代码

抽象模板类
  1. // GameTemplate.java 定义抽象模板类,有抽象方法和具体方法
  2. public abstract class GameTemplate {
  3.    // 抽象方法待子类来实现
  4.    abstract void init();
  5.    abstract void start();
  6.    abstract void end();
  7.    // 可复用的算法流程
  8.    public void play() {
  9.       System.out.println(this.getClass().getSimpleName() + "::play()");
  10.       // 初始化游戏
  11.       init();
  12.       // 开始游戏
  13.       start();
  14.       // 结束游戏
  15.       end();
  16.    }
  17. }
复制代码
具体业务类,继承抽象模板
  1. // Basketball.java  定义子类覆写父类抽象方法
  2. public class Basketball extends GameTemplate {
  3.    @Override
  4.    void init() {
  5.       System.out.println("Basketball::init() [Basketball Game Initialized! Start playing.]");
  6.    }
  7.    @Override
  8.    void start() {
  9.       System.out.println("Basketball::start() [Basketball Game Started. Enjoy the game!]");
  10.    }
  11.    @Override
  12.    void end() {
  13.       System.out.println("Basketball::end() [Basketball Game Finished!]");
  14.    }
  15. }
复制代码
  1. // Football.java 定义子类覆写父类抽象方法
  2. public class Football extends GameTemplate {
  3.    @Override
  4.    void init() {
  5.       System.out.println("Football::init() [Football Game Initialized! Start playing.]");
  6.    }
  7.    @Override
  8.    void start() {
  9.       System.out.println("Football::start() [Football Game Started. Enjoy the game!]");
  10.    }
  11.    @Override
  12.    void end() {
  13.       System.out.println("Football::end() [Football Game Finished!]");
  14.    }
  15. }
复制代码
  1. // Tennis.java 定义子类覆写父类抽象方法
  2. public class Tennis extends GameTemplate {
  3.    @Override
  4.    void init() {
  5.       System.out.println("Tennis::init() [Tennis Game Initialized! Start playing.]");
  6.    }
  7.    @Override
  8.    void start() {
  9.       System.out.println("Tennis::start() [Tennis Game Started. Enjoy the game!]");
  10.    }
  11.    @Override
  12.    void end() {
  13.       System.out.println("Tennis::end() [Tennis Game Finished!]");
  14.    }
  15.    // 在调用父类play之前,如果要执行自己的行为,也可以覆盖父类方法
  16.    // 先执行自己的,再调用父类的方法
  17.    @Override
  18.    public void play() {
  19.       System.out.println("Tennis::play() [Tennis Game play!]");
  20.       super.play();
  21.    }
  22. }
复制代码
测试调用
  1.     /**
  2.      * 模板方法模式就是当子类具备类似行为的时候,让子类共用一套流程
  3.      * 创建一个公共模板,确定公用流程和操作动作,子类覆盖具体的动作
  4.      */
  5.     GameTemplate football = new Football();
  6.     football.play();
  7.     System.out.println("===");
  8.     GameTemplate basketball = new Basketball();
  9.     basketball.play();
  10.     System.out.println("===");
  11.     GameTemplate tennis = new Tennis();
  12.     tennis.play();
复制代码
C语言代码

头文件

// func.h
  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <stdlib.h>
  4. #include <stdbool.h>
  5. #include <string.h>
  6. typedef struct GameTemplate GameTemplate;
  7. typedef struct Football Football;
  8. typedef struct Basketball Basketball;
  9. typedef struct Tennis Tennis;
  10. // 定义抽象模板,包括各种动作和公共流程
  11. typedef struct GameTemplate
  12. {
  13.   char name[50];
  14.   void (*init)(GameTemplate *game);
  15.   void (*start)(GameTemplate *game);
  16.   void (*end)(GameTemplate *game);
  17.   void (*play)(GameTemplate *game);
  18. } GameTemplate;
  19. void template_play(GameTemplate *game);
  20. GameTemplate *game_template_constructor(char *name);
  21. // 定义子类覆写父类抽象方法
  22. typedef struct Football
  23. {
  24.   char name[50];
  25.   void (*init)(Football *game);
  26.   void (*start)(Football *game);
  27.   void (*end)(Football *game);
  28.   void (*play)(Football *game);
  29. } Football;
  30. Football *football_constructor(char *name);
  31. // 定义子类覆写父类抽象方法
  32. typedef struct Basketball
  33. {
  34.   char name[50];
  35.   void (*init)(Basketball *game);
  36.   void (*start)(Basketball *game);
  37.   void (*end)(Basketball *game);
  38.   void (*play)(Basketball *game);
  39. } Basketball;
  40. Basketball *basketball_constructor(char *name);
  41. // 定义子类覆写父类抽象方法
  42. typedef struct Tennis
  43. {
  44.   char name[50];
  45.   void (*init)(Tennis *game);
  46.   void (*start)(Tennis *game);
  47.   void (*end)(Tennis *game);
  48.   void (*play)(Tennis *game);
  49. } Tennis;
  50. Tennis *tennis_constructor(char *name);
复制代码
抽象模板类
  1. // game_template.c 定义抽象模板类,有抽象方法和具体方法
  2. #include "func.h"
  3. // 定义抽象模板类的公共部分,这里用struct替代
  4. // 抽象方法待子类来实现
  5. void template_init(GameTemplate *game) {}
  6. void template_start(GameTemplate *game)
  7. {
  8.   printf("\r\n GameTemplate::start() [GameTemplate Initialized! Start playing.]");
  9. }
  10. void template_end(GameTemplate *game) {}
  11. // 可复用的算法流程
  12. void template_play(GameTemplate *game)
  13. {
  14.   printf("\r\n GameTemplate::play() [name=%s]", game->name);
  15.   // 初始化游戏
  16.   game->init(game);
  17.   // 开始游戏
  18.   game->start(game);
  19.   // 结束游戏
  20.   game->end(game);
  21. }
  22. GameTemplate *game_template_constructor(char *name)
  23. {
  24.   // printf("\r\n game_template_constructor() [构建GameTemplate]");
  25.   GameTemplate *game = (GameTemplate *)malloc(sizeof(GameTemplate));
  26.   strcpy(game->name, name);
  27.   game->init = &template_init;
  28.   game->start = &template_start;
  29.   game->end = &template_end;
  30.   game->play = &template_play;
  31.   return game;
  32. }
复制代码
具体业务类,继承抽象模板
  1. // basketball.c  定义子类覆写父类抽象方法
  2. #include "func.h"
  3. // 定义子类覆写父类抽象方法
  4. void basketball_init(Basketball *game)
  5. {
  6.   printf("\r\n Basketball::init() [Basketball Game Initialized! Start playing.]");
  7. }
  8. void basketball_start(Basketball *game)
  9. {
  10.   printf("\r\n Basketball::start() [Basketball Game Started. Enjoy the game!]");
  11. }
  12. void basketball_end(Basketball *game)
  13. {
  14.   printf("\r\n Basketball::end() [Basketball Game Finished!]");
  15. }
  16. Basketball *basketball_constructor(char *name)
  17. {
  18.   printf("\r\n basketball_constructor() [构建Basketball]");
  19.   GameTemplate *template = game_template_constructor(name);
  20.   Basketball *game = (Basketball *)template;
  21.   game->init = &basketball_init;
  22.   // 如果不覆盖则使用基类的函数
  23.   // game->start = &basketball_start;
  24.   game->end = &basketball_end;
  25.   return game;
  26. }
复制代码
  1. // football.c 定义子类覆写父类抽象方法
  2. #include "func.h"
  3. // 定义子类覆写父类抽象方法
  4. void football_init(Football *game)
  5. {
  6.   printf("\r\n Football::init() [Football Game Initialized! Start playing.]");
  7. }
  8. void football_start(Football *game)
  9. {
  10.   printf("\r\n Football::start() [Football Game Started. Enjoy the game!]");
  11. }
  12. void football_end(Football *game)
  13. {
  14.   printf("\r\n Football::end() [Football Game Finished!]");
  15. }
  16. Football *football_constructor(char *name)
  17. {
  18.   printf("\r\n football_constructor() [构建Football]");
  19.   GameTemplate *template = game_template_constructor(name);
  20.   Football *game = (Football *)template;
  21.   game->init = &football_init;
  22.   game->start = &football_start;
  23.   game->end = &football_end;
  24.   return game;
  25. }
复制代码
  1. // tennis.c 定义子类覆写父类抽象方法
  2. #include "func.h"
  3. // 定义子类覆写父类抽象方法
  4. void tennis_init(Tennis *game)
  5. {
  6.   printf("\r\n Tennis::init() [Tennis Game Initialized! Start playing.]");
  7. }
  8. void tennis_start(Tennis *game)
  9. {
  10.   printf("\r\n Tennis::start() [Tennis Game Started. Enjoy the game!]");
  11. }
  12. void tennis_end(Tennis *game)
  13. {
  14.   printf("\r\n Tennis::end() [Tennis Game Finished!]");
  15. }
  16. // 在调用父类play之前,如果要执行自己的行为,也可以覆盖父类方法
  17. void tennis_play(Tennis *game)
  18. {
  19.   // 先执行自己的内容,再调用基类的函数
  20.   printf("\r\n Tennis::play() [Tennis Game Play!]");
  21.   template_play((GameTemplate *)game);
  22. }
  23. Tennis *tennis_constructor(char *name)
  24. {
  25.   printf("\r\n tennis_constructor() [构建Tennis]");
  26.   GameTemplate *template = game_template_constructor(name);
  27.   Tennis *game = (Tennis *)template;
  28.   game->init = &tennis_init;
  29.   game->start = &tennis_start;
  30.   game->end = &tennis_end;
  31.   game->play = &tennis_play;
  32.   return game;
  33. }
复制代码
测试调用
  1. #include "../src/func.h"
  2. int main(void)
  3. {
  4.   printf("test start:\r\n");
  5.   /**
  6.    * 模板方法模式就是当子类具备类似行为的时候,让子类共用一套流程
  7.    * 创建一个公共模板,确定公用流程和操作动作,子类覆盖具体的动作
  8.    */
  9.   Football *football = football_constructor("football");
  10.   football->play(football);
  11.   printf("\r\n ===");
  12.   Basketball *basketball = basketball_constructor("basketball");
  13.   basketball->play(basketball);
  14.   printf("\r\n ===");
  15.   Tennis *tennis = tennis_constructor("basketball");
  16.   tennis->play(tennis);
  17. }
复制代码
更多语言版本

不同语言设计模式源码:https://github.com/microwind/design-pattern

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册