简介

模板办法形式(Template Method Pattern)也叫模板形式,是一种行为型形式。它界说了一个笼统公开类,包含根本的算法骨架,而将一些进程延迟到子类中,模板办法使得子类能够不改变算法的结构,只是重界说该算法的某些特定进程。不同的子类以不同的方式完结这些笼统办法,从而对剩余的逻辑有不同的完结。以此基于公共的模板,来完结完结不同的功用。

模板形式适用于一些复杂操作进行进程分割、抽取公共部分由笼统父类完结、将不同的部分在父类中界说笼统完结、而将详细完结进程由子类完结。对于有多个子类具有共有的办法,且逻辑相同,能够考虑作为模板办法。

作用

  1. 相同的部分父类给出一致的模板,子类大量复用,从而节省代码,复用逻辑。
  2. 封装不变部分,扩展可变部分,行为由父类操控,子类灵敏完结,便于保护和扩展。

完结进程

  1. 创立一个笼统的模板类,界说根本流程,同时界说一些根本办法供子类去完结。
  2. 创立多个子类承继笼统模板,掩盖父类的相关动作和办法。

UML

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

Java代码

笼统模板类

// GameTemplate.java 界说笼统模板类,有笼统办法和详细办法
public abstract class GameTemplate {
   // 笼统办法待子类来完结
   abstract void init();
   abstract void start();
   abstract void end();
   // 可复用的算法流程
   public void play() {
      System.out.println(this.getClass().getSimpleName() + "::play()");
      // 初始化游戏
      init();
      // 开端游戏
      start();
      // 结束游戏
      end();
   }
}

详细事务类,承继笼统模板

// Basketball.java  界说子类覆写父类笼统办法
public class Basketball extends GameTemplate {
   @Override
   void init() {
      System.out.println("Basketball::init() [Basketball Game Initialized! Start playing.]");
   }
   @Override
   void start() {
      System.out.println("Basketball::start() [Basketball Game Started. Enjoy the game!]");
   }
   @Override
   void end() {
      System.out.println("Basketball::end() [Basketball Game Finished!]");
   }
}
// Football.java 界说子类覆写父类笼统办法
public class Football extends GameTemplate {
   @Override
   void init() {
      System.out.println("Football::init() [Football Game Initialized! Start playing.]");
   }
   @Override
   void start() {
      System.out.println("Football::start() [Football Game Started. Enjoy the game!]");
   }
   @Override
   void end() {
      System.out.println("Football::end() [Football Game Finished!]");
   }
}
// Tennis.java 界说子类覆写父类笼统办法
public class Tennis extends GameTemplate {
   @Override
   void init() {
      System.out.println("Tennis::init() [Tennis Game Initialized! Start playing.]");
   }
   @Override
   void start() {
      System.out.println("Tennis::start() [Tennis Game Started. Enjoy the game!]");
   }
   @Override
   void end() {
      System.out.println("Tennis::end() [Tennis Game Finished!]");
   }
   // 在调用父类play之前,如果要履行自己的行为,也能够掩盖父类办法
   // 先履行自己的,再调用父类的办法
   @Override
   public void play() {
      System.out.println("Tennis::play() [Tennis Game play!]");
      super.play();
   }
}

测试调用

    /**
     * 模板办法形式就是当子类具备类似行为的时分,让子类共用一套流程
     * 创立一个公共模板,确认共用流程和操作动作,子类掩盖详细的动作
     */
    GameTemplate football = new Football();
    football.play();
    System.out.println("===");
    GameTemplate basketball = new Basketball();
    basketball.play();
    System.out.println("===");
    GameTemplate tennis = new Tennis();
    tennis.play();

C言语代码

头文件

// func.h

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct GameTemplate GameTemplate;
typedef struct Football Football;
typedef struct Basketball Basketball;
typedef struct Tennis Tennis;
// 界说笼统模板,包括各种动作和公共流程
typedef struct GameTemplate
{
  char name[50];
  void (*init)(GameTemplate *game);
  void (*start)(GameTemplate *game);
  void (*end)(GameTemplate *game);
  void (*play)(GameTemplate *game);
} GameTemplate;
void template_play(GameTemplate *game);
GameTemplate *game_template_constructor(char *name);
// 界说子类覆写父类笼统办法
typedef struct Football
{
  char name[50];
  void (*init)(Football *game);
  void (*start)(Football *game);
  void (*end)(Football *game);
  void (*play)(Football *game);
} Football;
Football *football_constructor(char *name);
// 界说子类覆写父类笼统办法
typedef struct Basketball
{
  char name[50];
  void (*init)(Basketball *game);
  void (*start)(Basketball *game);
  void (*end)(Basketball *game);
  void (*play)(Basketball *game);
} Basketball;
Basketball *basketball_constructor(char *name);
// 界说子类覆写父类笼统办法
typedef struct Tennis
{
  char name[50];
  void (*init)(Tennis *game);
  void (*start)(Tennis *game);
  void (*end)(Tennis *game);
  void (*play)(Tennis *game);
} Tennis;
Tennis *tennis_constructor(char *name);

笼统模板类

// game_template.c 界说笼统模板类,有笼统办法和详细办法
#include "func.h"
// 界说笼统模板类的公共部分,这里用struct代替
// 笼统办法待子类来完结
void template_init(GameTemplate *game) {}
void template_start(GameTemplate *game)
{
  printf("\r\n GameTemplate::start() [GameTemplate Initialized! Start playing.]");
}
void template_end(GameTemplate *game) {}
// 可复用的算法流程
void template_play(GameTemplate *game)
{
  printf("\r\n GameTemplate::play() [name=%s]", game->name);
  // 初始化游戏
  game->init(game);
  // 开端游戏
  game->start(game);
  // 结束游戏
  game->end(game);
}
GameTemplate *game_template_constructor(char *name)
{
  // printf("\r\n game_template_constructor() [构建GameTemplate]");
  GameTemplate *game = (GameTemplate *)malloc(sizeof(GameTemplate));
  strcpy(game->name, name);
  game->init = &template_init;
  game->start = &template_start;
  game->end = &template_end;
  game->play = &template_play;
  return game;
}

详细事务类,承继笼统模板

// basketball.c  界说子类覆写父类笼统办法
#include "func.h"
// 界说子类覆写父类笼统办法
void basketball_init(Basketball *game)
{
  printf("\r\n Basketball::init() [Basketball Game Initialized! Start playing.]");
}
void basketball_start(Basketball *game)
{
  printf("\r\n Basketball::start() [Basketball Game Started. Enjoy the game!]");
}
void basketball_end(Basketball *game)
{
  printf("\r\n Basketball::end() [Basketball Game Finished!]");
}
Basketball *basketball_constructor(char *name)
{
  printf("\r\n basketball_constructor() [构建Basketball]");
  GameTemplate *template = game_template_constructor(name);
  Basketball *game = (Basketball *)template;
  game->init = &basketball_init;
  // 如果不掩盖则运用基类的函数
  // game->start = &basketball_start;
  game->end = &basketball_end;
  return game;
}
// football.c 界说子类覆写父类笼统办法
#include "func.h"
// 界说子类覆写父类笼统办法
void football_init(Football *game)
{
  printf("\r\n Football::init() [Football Game Initialized! Start playing.]");
}
void football_start(Football *game)
{
  printf("\r\n Football::start() [Football Game Started. Enjoy the game!]");
}
void football_end(Football *game)
{
  printf("\r\n Football::end() [Football Game Finished!]");
}
Football *football_constructor(char *name)
{
  printf("\r\n football_constructor() [构建Football]");
  GameTemplate *template = game_template_constructor(name);
  Football *game = (Football *)template;
  game->init = &football_init;
  game->start = &football_start;
  game->end = &football_end;
  return game;
}
// tennis.c 界说子类覆写父类笼统办法
#include "func.h"
// 界说子类覆写父类笼统办法
void tennis_init(Tennis *game)
{
  printf("\r\n Tennis::init() [Tennis Game Initialized! Start playing.]");
}
void tennis_start(Tennis *game)
{
  printf("\r\n Tennis::start() [Tennis Game Started. Enjoy the game!]");
}
void tennis_end(Tennis *game)
{
  printf("\r\n Tennis::end() [Tennis Game Finished!]");
}
// 在调用父类play之前,如果要履行自己的行为,也能够掩盖父类办法
void tennis_play(Tennis *game)
{
  // 先履行自己的内容,再调用基类的函数
  printf("\r\n Tennis::play() [Tennis Game Play!]");
  template_play((GameTemplate *)game);
}
Tennis *tennis_constructor(char *name)
{
  printf("\r\n tennis_constructor() [构建Tennis]");
  GameTemplate *template = game_template_constructor(name);
  Tennis *game = (Tennis *)template;
  game->init = &tennis_init;
  game->start = &tennis_start;
  game->end = &tennis_end;
  game->play = &tennis_play;
  return game;
}

测试调用

#include "../src/func.h"
int main(void)
{
  printf("test start:\r\n");
  /**
   * 模板办法形式就是当子类具备类似行为的时分,让子类共用一套流程
   * 创立一个公共模板,确认共用流程和操作动作,子类掩盖详细的动作
   */
  Football *football = football_constructor("football");
  football->play(football);
  printf("\r\n ===");
  Basketball *basketball = basketball_constructor("basketball");
  basketball->play(basketball);
  printf("\r\n ===");
  Tennis *tennis = tennis_constructor("basketball");
  tennis->play(tennis);
}

更多言语版本

不同言语规划形式源码:github.com/microwind/d…