用 C 语言编写设计模式--模板模式

往期回顾:

    1. 用 C 语言实现简单工厂模式!

    2. 用 C 语言编写建造者模式!

    3. 用C语言实现原型模式!

    4. 用 C 语言实现一个静态代理模式 !

    5. C语言实现设计模式--装饰模式!

    6. 用C语言实现适配器模式!

👀

1.概念

Template Method 模式也叫模板方法模式,是行为模式之一,它把具有特定步骤算法中的某些必要的处理委让给抽象方法,通过子类继承对抽象方法的不同实现改变整个算法的行为。

👀

2.应用场景

Template Method 模式一般应用在具有以下条件的应用中:

1. 具有统一的操作步骤或操作过程。

  • 2. 具有不同的操作细节。

  • 3. 存在多个具有同样操作步骤的应用场景,但某些具体的操作细节却各不相同。

👀

3.实例设计

1.本篇以 CPU 初始化流程为例对模板模式进行说明,例如 CPU 的初始化流程都大致一样,初始化硬盘、外设、内存、网络等,但是每个 CPU 初始化具体的细节却不相同,即初始化流程可以看作一个模板,有统一的操作步骤,但具有不同的操作细节。下面以 Intel CPU 和 AMD CPU 初始化为例。

2.首先定义抽象接口:初始化外设、硬盘、内存、网络等,init()函数即是模板,包含整个初始化流程,即外部调用一个 init()函数即可对 CPU 进行初始化。

typedef struct Interface_t
{
    /*初始化外设USB、SPI、IIC等*/
    void (*init_peripheral)(void *obj); 
    
    /*初始化硬盘*/
    void (*init_disk)(void* obj);
    
    /*初始化内存*/
    void (*init_memory)(void* obj);
    
    /*初始化网络*/
    void (*init_net)(void *obj);
    
    /*对整个流程初始化*/
    void (*init)(void *obj);
}Interface_t;

3.AMD CPU 初始化相关定义,Intel CPU 相关代码实现与下面的实现几乎一致,此处不再贴代码。

//定义一个Intel CPU初始化结构体
typedef struct AMDCpuStart_t
{
    void (*init_peripheral)(void *obj); //初始化外设    
    void (*init_disk)(void* obj);       //初始化硬盘 
    void (*init_memory)(void* obj);     //初始化内存
    void (*init_net)(void *obj);        //初始化网络
    void (*init)(void *obj);            //模块 整个初始化流程
}AMDCpuStart_t;
static void ADM_init_peripheral(void *obj)
{   
    printf("初始化AMD 外设...\n");
}
static void ADM_init_disk(void *obj)
{   
    printf("初始化AMD 硬盘...\n");
}
static void ADM_init_memory(void *obj)
{   
    printf("初始化AMD 内存...\n");
}
static void ADM_init_net(void *obj)
{   
    printf("初始化AMD 网络...\n");
}
//初始化模板
static void ADM_init(void *obj)
{   
    AMDCpuStart_t *amd = (AMDCpuStart_t*)obj;
    printf("AMD CPU 上电初始化流程: \n");
    amd->init_peripheral(amd);
    amd->init_disk(amd);
    amd->init_memory(amd);
    amd->init_net(amd);
}   
//AMD构造函数 创建一个结构体指针
AMDCpuStart_t* construct_amd_cpu(void)
{
    AMDCpuStart_t* obj = (AMDCpuStart_t*)malloc(sizeof(AMDCpuStart_t));
    obj->init = ADM_init;
    obj->init_disk = ADM_init_disk;
    obj->init_memory = ADM_init_memory;
    obj->init_net = ADM_init_net;
    obj->init_peripheral = ADM_init_peripheral;
    
    return obj;
}

👀

   4.测试与验证

测试程序:如下,先创建一个 AMD 的对象,调用 init()模块进行初始化,然后对 init_peripheral()init_disk()指向新的函数,修改接口,这样保证了我们模块流程不变,但是可以改变一些具体的细节。最后创建 Intel 对象,调用 init()函数模板进行初始化。​​​​​​​

//二次重写 AMD 外设初始化程序
void ADM_init_peripheral_v1(void *obj)
{
    printf("新接口: 初始化 ADM 的外设: USB3.0、SPI、IIC接口...\n");
}
//二次重写 AMD 硬盘初始化程序
void ADM_init_disk_V1(void *obj)
{   
    printf("新接口: 初始化AMD 硬盘: 三星固态硬盘(512G)、东芝固态硬盘(128G)...\n");
}
int main(void)
{   
    Interface_t *cpu=NULL;
    //创建一个AMD对象
    cpu = (Interface_t*)construct_amd_cpu(); 
    //调用模板 初始化AMD CPU
    cpu->init(cpu);
    printf("\n二次重写的硬盘和外设初始化接口:\n");
    //给函数指针二次赋值(等于重写),便于修改添加新概念
    cpu->init_peripheral = ADM_init_peripheral_v1;
    //给函数指针二次赋值(等于重写),便于修改添加新概念
    cpu->init_disk = ADM_init_disk_V1;
    //调用模块,修改了初始化硬盘、初始化外设接口
    cpu->init(cpu);
    free(cpu);
    cpu = NULL;
    printf("\n");
    //创建一个Intel CPU对象
    cpu = (Interface_t*)construct_intel_cpu();
    //调用Intel CPU初始化模板
    cpu->init(cpu);
    free(cpu);
    cpu = NULL;
    return 0;
}


测试结果: 与预期一致,第二次调用amd的init()模板时,使用的就是新接口的功能。

5.总结

  1. 模板模式 总结: 在抽象类中统一操作步骤,并规定好接口;让子类实现接口。这样可以把各个具体的子类和操作步骤解耦合

  2. 虽然C语言是面向过程的编程语言,但是我们在设计程序的时候,可以考虑用面向对象的方式去设计,这样提高我们程序的“高内聚、低耦合”特性,便于维护。

需要C语言实现设计模式代码的小伙伴:在微信公众号【Linux编程用C】后台回复 【designer】 即可获取,不断更新中!

欢迎大家加小C微信【LinuxCodeUseC】,我们一起交流讨论学习!

PS:若大家想看C语言版本的其他设计模式,

请大家 点赞! 转发!关注吧!~~

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值