我用C语言玩对象,框架化的模板模式

概念

模板模式(Template Pattern)模式:属于行为型模式,对于某一个业务逻辑(算法实现)在不同的对象中有不同的细节实现,但是整体处理/算法逻辑的框架是一致的。Template提供了一个实现框架

注意

1、也可以使用C语言宏定义来实现一些简单模板类,需要定义多个函数,然后采用##的方式,访问函数和类型等等,传入参数包括类型,个人感觉比较冗余。

2、在通用双向链表中同样使用了模板方法实现,做到兼容多种类型链表,具体见通用双向链表篇。

如:对于字符串和整数链表,分别实现节点信息比较和输出函数,在类的创建的时候,传递对应方法即可。对于类内部而言,删除指定信息节点、查找指定信息节点,链表输出等方法执行对于不同链表流程均一致。

介绍

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

主要解决:一些方法通用,却在每一个子类都重新写了这一方法

何时使用:有一些通用的方法。

如何解决:将这些通用算法抽象出来。

关键代码:在抽象类实现,其他步骤在子类实现。

核心

定义一个抽象类公开执行它的方法的方式/模板,子类继承的时候按需重写方法,但调用将以抽象类中定义的方式进行。

示例

★背景说明:假如新生刚刚入校,为了让大家相互了解一下,此时班主任让每一位同学依次:起立->自我介绍->坐下。。 

★学生对象:

属性:姓名

行为:起立、自我介绍、坐下、动作集合。

★可以认为“起立->自我介绍->坐下”是一个流程框架,其中所有同学站起和坐下的动作是一样的,但是每一位同学的自我介绍都是不一样的,动作集合就包含整个流程,而自我介绍可以在类创建的时候通过函数指针传递。

★包含头文件student.h和源文件student.c(均已验证通过)。

 student.h

/**
 * @Filename : student.h
 * @Revision : $Revision: 1.0 $
 * @Author : Feng(更多编程相关的知识和源码见微信公众号:不只会拍照的程序猿,欢迎订阅)
 * @Description : 模板模式应用(C语言模拟C++)
 * @Explain : 假如新生刚入校,班主任让每一位同学依次:起立->自我介绍->坐下
              seven  student   会跳舞
              feng   student   会唱歌       
**/

#ifndef __STUDENT_H__
#define __STUDENT_H__

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct student;

typedef void (*pFuncIntroduction)(struct student *p_student);    /* 自我介绍 */

/* 学生类定义 */
struct student {
    char name[16];  /* 名字 */

    void (*up)(struct student *p_student);            /* 起立 */
    void (*introduction)(struct student *p_student);  /* 自我介绍 */
    void (*down)(struct student *p_student);          /* 坐下 */
    void (*action)(struct student *p_student);        /* 学生动作 */
};

/* 创建学生对象 */
struct student *new_student(char *name, pFuncIntroduction _introduction);

#endif

 student.c

/**
 * @Filename : student.c
 * @Revision : $Revision: 1.0 $
 * @Author : Feng(更多编程相关的知识和源码见微信公众号:不只会拍照的程序猿,欢迎订阅)
 * @Description : 模板模式应用(C语言模拟C++)
 * @Explain : 假如新生刚入校,班主任让每一位同学依次:起立->自我介绍->坐下
              seven  student   会跳舞
              feng   student   会唱歌       
**/

#include "student.h"

/**
 * @站立
 * @p_student:学生类                      
**/
void _up(struct student *p_student)
{
    printf("%s stand up...\n", p_student->name);
}

/**
 * @seven自我介绍,会跳舞
 * @p_student:学生类                      
**/
void _introductionSeven(struct student *p_student)
{
    printf("%s can dancing...\n", p_student->name);
}

/**
 * @feng自我介绍,会唱歌
 * @p_student:学生类                      
**/
void _introductionFeng(struct student *p_student)
{
    printf("%s can sing...\n", p_student->name);
}

/**
 * @坐下
 * @p_student:学生类                      
**/
void _down(struct student *p_student)
{
    printf("%s sit down...\n", p_student->name);
}

/**
 * @动作集合  起立->自我介绍->坐下
 * @p_student:学生类                       
**/
void _action(struct student *p_student)
{
    p_student->up(p_student);   
    p_student->introduction(p_student);
    p_student->down(p_student);
}

/**
 * @创建student对象
 * @name:姓名
 * @_introduction:自我介绍函数
 * @成功返回类对象,失败返回NULL                         
**/
struct student *new_student(char *name, pFuncIntroduction _introduction)
{
    struct student *p_student = (struct student *)malloc(sizeof(struct student));

    if (p_student == NULL)
        return NULL;

    memset((char *)p_student, 0, sizeof(struct student));

    strcpy(p_student->name, name);

    p_student->up = _up;
    p_student->introduction = _introduction;
    p_student->down = _down;
    p_student->action = _action;

    return p_student;
}

/**
 * @主函数,演示代码                      
**/
int main(void)
{   
    /* 创建了 seven 和 feng 两个学生对象 */
    struct student *p_seven = new_student("seven", _introductionSeven);
    struct student *p_feng = new_student("feng", _introductionFeng);

    if ((p_seven == NULL) || (p_feng == NULL)) {
        printf("create observable class failed...\n");
        return -1;
    }

    /* feng 开始进行自我介绍 */
    printf("feng introduction:\n");
    p_feng->action(p_feng);        
    printf("**************************************\n");

    /* seven 开始进行自我介绍 */
    printf("seven introduction:\n");
    p_seven->action(p_seven);    

    return 0;
}

结论

feng@feng-vm:~/share/template$ gcc -o student student.c
feng@feng-vm:~/share/template$ ./student
feng introduction:
feng stand up...
feng can sing...
feng sit down...
**************************************
seven introduction:
seven stand up...
seven can dancing...
seven sit down...
feng@feng-vm:~/share/template$ 

分析:首先定义了抽象类student,action行为用于表明一套动作的集合包含up->introduction->down,动作的过程和调用不变,seven和feng均继承student类,并且改写了introduction方法,实现特定步骤的差异性,而并不改变整个过程的结构。

往期 · 推荐

也没想象中那么神秘的数据结构-先来后到的“队列”(链式队列)

也没想象中那么神秘的数据结构-先来后到的“队列”(循环队列)

也没想象中那么神秘的数据结构-后来居上的“栈”

我用C语言玩对象,观察者模式应用2-热水的用途

我用C语言玩对象,状态模式应用1-水的三态

关注

更多精彩内容,请关注微信公众号:不只会拍照的程序猿,本人致力分享linux、设计模式、C语言、嵌入式、编程相关知识,也会抽空分享些摄影相关内容,同样也分享大量摄影、编程相关视频和源码,另外你若想要本文章源码请关注公众号:不只会拍照的程序猿,后台回复:设计模式源码,也可点击此处下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不只会拍照的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值