7.设计模式-模板方法模式

定义:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤

需求

实现一个抄写试卷题目的程序

需求分析

  • 识别出变化的内容,只将变化定义在子类,其他定义在父类

代码实现

模板类

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PAPERMAXQUESTION 10
typedef struct TestPaper {
    char *testQuestion[PAPERMAXQUESTION];
    char *answers[PAPERMAXQUESTION];
    int questionNum;
    int answerNum;
    void (*SetQuestion)(struct TestPaper *);
    void (*PrintQuestion)(struct TestPaper *);
    void (*AddQuestion)(struct TestPaper *, char *);
    // 在模板类不定义
    void (*SetAnswer)(struct TestPaper *);
}TestPaper;

void AddQuestion(struct TestPaper *obj, char *question) {
    obj->testQuestion[(obj->questionNum)++] = question;
    return;
}
void SetQuestion(TestPaper *obj) {
    obj->AddQuestion(obj, "杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是[ ] \na.球磨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维");
    obj->AddQuestion(obj, "杨过、程英、陆无双铲除了情花,造成[ ] \na.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化");
    obj->AddQuestion(obj, "蓝凤凰致使华山师徒、桃谷六仙呕吐不止,如果你是大夫,会给他们开什么药[ ]\na.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的生牛奶 e.以上全不对");
    return;
}
void PrintQuestion(TestPaper *obj) {
    printf("===============================================\n");
    printf("试验:%d道试题\n", obj->questionNum);
    for(int i=0; i<obj->questionNum; i++) {
        printf("题目%d:%s\n", i+1, obj->testQuestion[i]);
        printf("答案:%s\n", obj->answers[i]);
    }
}

TestPaper *InitTestPaper() {
    TestPaper *obj = (TestPaper *)malloc(sizeof(TestPaper));
    obj->PrintQuestion = PrintQuestion;
    obj->AddQuestion = AddQuestion;
    obj->SetQuestion = SetQuestion;
    obj->questionNum = 0;
    obj->questionNum = 0;
    memset(obj->testQuestion, 0, sizeof(char *)*PAPERMAXQUESTION);
    memset(obj->answers, 0, sizeof(char *)*PAPERMAXQUESTION);
    obj->SetQuestion(obj);
    return obj;
}

具体类

c 复制代码
typedef struct TestPaperA {
    TestPaper base;
}TestPaperA;
void PaperASetAnswer(TestPaper *obj) {
    obj->answers[obj->answerNum++] = "b";
    obj->answers[obj->answerNum++] = "b";
    obj->answers[obj->answerNum++] = "b";
    return;
}
TestPaperA *InitTestPaperA() {
    TestPaperA *obj = (TestPaperA *)malloc(sizeof(TestPaperA));
    TestPaper *tmp = InitTestPaper();
    obj->base = *tmp;
    free(tmp);
    // 子类只定义一个设置答案接口
    obj->base.SetAnswer = PaperASetAnswer;
    obj->base.SetAnswer((TestPaper *)obj);
    return obj;
}
typedef struct TestPaperB {
    TestPaper base;
}TestPaperB;
void PaperBSetAnswer(TestPaper *obj) {
    obj->answers[obj->answerNum++] = "c";
    obj->answers[obj->answerNum++] = "c";
    obj->answers[obj->answerNum++] = "c";
    return;
}
TestPaperB *InitTestPaperB() {
    TestPaperB *obj = (TestPaperB *)malloc(sizeof(TestPaperB));
    TestPaper *tmp = InitTestPaper();
    obj->base = *tmp;
    free(tmp);
    obj->base.SetAnswer = PaperBSetAnswer;
    obj->base.SetAnswer((TestPaper *)obj);
    return obj;
}

客户端

c 复制代码
int main() {
    TestPaperA *paperA = InitTestPaperA();
    ((TestPaper *)paperA)->PrintQuestion((TestPaper *)paperA);
    TestPaperB *paperB = InitTestPaperB();
    ((TestPaper *)paperB)->PrintQuestion((TestPaper *)paperB);
    return 0;
}

UML图

总结

  • 模板方法模式应用场景?当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。我们通过模板方法模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠。
相关推荐
强哥聊算力5 小时前
《算力江湖·英伟达传奇》第七集:ChatGPT出现前夜,英伟达发生了什么?
服务器·人工智能·算法·ai·chatgpt·gpu算力
Navigator_Z8 小时前
LeetCode //C - 1289. Minimum Falling Path Sum II
c语言·算法·leetcode
CCblandy9 小时前
令牌桶在 0.9 倍负载超发 19%、固定窗口边界放行 20 个:四种限流算法同构实测
后端·python·算法·性能优化·架构
YangYang9YangYan10 小时前
2027供应链计划校招:数学与应用数学专业如何把预测模型讲成业务决策?
人工智能·sql·算法
jsjzsl210 小时前
递归自改进系统(RSI)的本质是自发对称破缺:智能爆炸有界—— AI研发切记盲目投入
人工智能·python·算法
程序员清风10 小时前
最短路径算法:BFS、Dijkstra 与 Floyd
java·算法·宽度优先
梦帮科技10 小时前
Kali Linux Scapy 畸形报文构造学——深度解剖非法 TCP Flags 与反常序列号
linux·爬虫·神经网络·算法·数学建模·系统架构·模拟退火算法
171320330计算机毕设编程12 小时前
计算机毕业设计 基于YOLO改进算法的车辆特征识别系统设计与实现--lw
java·大数据·python·sql·算法
姜鱼问生12 小时前
Nginx gzip 压缩:一个配置让页面加载快 3 倍
后端·算法·架构