簡介 模板方法模式(Template Method Pattern)也叫模板模式,是一種行為型模式。它定義了一個抽象公開類,包含基本的演算法骨架,而將一些步驟延遲到子類中,模板方法使得子類可以不改變演算法的結構,只是重定義該演算法的某些特定步驟。不同的子類以不同的方式實現這些抽象方法,從而對剩餘的邏輯有不 ...
簡介
模板方法模式(Template Method Pattern)也叫模板模式,是一種行為型模式。它定義了一個抽象公開類,包含基本的演算法骨架,而將一些步驟延遲到子類中,模板方法使得子類可以不改變演算法的結構,只是重定義該演算法的某些特定步驟。不同的子類以不同的方式實現這些抽象方法,從而對剩餘的邏輯有不同的實現。以此基於公共的模板,來實現實現不同的功能。
模板模式適用於一些複雜操作進行步驟分割、抽取公共部分由抽象父類實現、將不同的部分在父類中定義抽象實現、而將具體實現過程由子類完成。對於有多個子類具有共有的方法,且邏輯相同,可以考慮作為模板方法。
作用
- 相同的部分父類給出統一的模板,子類大量復用,從而節省代碼,復用邏輯。
- 封裝不變部分,擴展可變部分,行為由父類控制,子類靈活實現,便於維護和擴展。
實現步驟
- 創建一個抽象的模板類,定義基本流程,同時定義一些基本方法供子類去實現。
- 創建多個子類繼承抽象模板,覆蓋父類的相關動作和方法。
UML
template-pattern.pngJava代碼
抽象模板類
// 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);
}
更多語言版本
不同語言設計模式源碼:https://github.com/microwind/design-pattern