【无标题】

用C语言编写建造者模式

一、简介

建造者模式: 也称生成器模式,是23种设计模式中的一种,是一种创建型模式。
适用情况:一个对象比较复杂,将一个对象的构建和对象的表示进行分离。
比较:与工厂模式进行对比,工厂模式不考虑对象部件组装过程,直接生成一个最终的对象,强调的是 结果 。而建造者模式先构建对象的每一个部件,然后再统一组建成一个对象,强调的是 过程
目的:实现复杂对象的生产流程与部件进行解耦。

二、设计实现

  1. 以建造房子为例,房子有公寓、别墅、楼房等类型,虽然是不同种类的房子,但其却过程大体上都相同,例如都有这些流程:修建墙、窗户、门、楼顶等。
  2. 我们实现Builder(建造者)建房,因为都有修建(墙、窗户、门、楼等)这些部件,但是具体实现却不同,所以我们需要把实现这些组建的操作给抽象出来,把每个部件实现了,然后再组装起来,修建的房子就完成了。
    设计建造者抽象接口如下
  3. 通过指针函数与结构体进行抽象,如不了解,请参考上一篇介绍。
typedef struct IBuilder_t           //建造者抽象接口
{
    void (*make_floor)(void *obj);  //修建地板
    void (*make_door)(void *obj);   //修建门
    void (*make_wall)(void *obj);   //修建墙
    void (*make_window)(void *obj); //修建窗
    void (*destory)(void *obj);     //释放内存
    House_t *house;                 //house对象
}IBuilder_t;
  1. 定义房子对象,然后房子里面的部件(墙、窗、门、地板等)交给建造者设置修建。
typedef struct House_t  //定义房子要实现的接口
{
    void (*setfloor)(struct House_t* obj, char *floor);
    void (*setdoor)(struct House_t* obj, char *door);
    void (*setwall)(struct House_t* obj, char *wall);
    void (*setwindow)(struct House_t* obj, char *window);

    char floor[32];         //地板名字
    char door[32];          //门名字
    char wall[32];          //墙名字
    char window[32];        //窗名字
}House_t;

//修建的地板类型。
//static修饰,不让外部直接调用这个函数,
//一般这些函数的实现放到.c文件中,结构体定义在.h文件中,
//而是通过House_t结构体的setfloor()函数指针进行调用,起到封装效果(下同)。
static void house_setfloor(House_t* obj, char *floor)
{
    if(obj)
        sprintf(obj->floor, "%s", floor);
}

//修建的门类型
static void house_setdoor(House_t* obj, char *door)
{
    if(obj)
        sprintf(obj->door, "%s", door);
}

//修建的墙类型
static void house_setwall(House_t* obj, char *wall)
{
    if(obj)
        sprintf(obj->wall, "%s", wall);
}

//修建的窗类型
static void house_setwindow(House_t* obj, char *window)
{
    if(obj)
        sprintf(obj->window, "%s", window);
}

//构造函数 创建一个房子的对象
//此处这个函数不能适用static修饰
//该函数是要开放被外部调用的
House_t* constructor_house(void)
{
    House_t* house = (House_t*)malloc(sizeof(House_t)); //申请对象
    house->setdoor = house_setdoor;    //函数指针赋值
    house->setfloor = house_setfloor;  //函数指针赋值
    house->setwall = house_setwall;    //函数指针赋值  
    house->setwindow = house_setwindow;//函数指针赋值
    return house;                      //返回一个房子对象
}
  1. 接下来我们实现builder,修建一个公寓。
    注:另外一个修建别墅实现,与修建公寓实现几乎完全一致,此处不做过多阐述。
//建造公寓的结构体,与IBuilder_t定义一致,即对IBuilder_t的实现
typedef struct FlatBuilder_t 
{
    void (*make_floor)(void *obj);
    void (*make_door)(void *obj);
    void (*make_wall)(void *obj);
    void (*make_window)(void *obj);
    void (*destory)(void *obj);
    House_t *house;
}FlatBuilder_t;

//建造地板。static修饰作用同上
static void flat_make_floor(void *obj)
{
    FlatBuilder_t* flat = (FlatBuilder_t*)obj;
    flat->house->setfloor(flat->house, "修建:flat floor");
}

//建造门
static void flat_make_door(void *obj)
{
    FlatBuilder_t* flat = (FlatBuilder_t*)obj;
    flat->house->setdoor(flat->house, "修建:flat door");
}

//建造墙
static void flat_make_wall(void *obj)
{
    FlatBuilder_t* flat = (FlatBuilder_t*)obj;
    flat->house->setwall(flat->house, "修建:flat wall");
}

//建造窗
static void flat_make_window(void *obj)
{
    FlatBuilder_t* flat = (FlatBuilder_t*)obj;
    flat->house->setwindow(flat->house, "修建:flat window");
}

//释放内存的函数
static void flat_destory(void *obj)
{
    FlatBuilder_t* flat = (FlatBuilder_t*)obj;
    if(flat->house) free(flat->house); //首先先释放flat包含的house内存
    flat->house=NULL;
    free(flat);                        //其次再释放当前对象
    flat=NULL;
}

//公寓建造者的构造函数,此处不能采用static修饰,因为其要被外部调用
FlatBuilder_t* constructor_flat_builder(void)
{
    FlatBuilder_t* flat = (FlatBuilder_t*)malloc(sizeof(FlatBuilder_t));
    flat->house = constructor_house();
    flat->make_door = flat_make_door;
    flat->make_floor = flat_make_floor;
    flat->make_wall = flat_make_wall;
    flat->make_window = flat_make_window;
    flat->destory = flat_destory;
    return flat;
}

三、测试

main函数里面的测试代码如下:
定义一个IBuilder_t *buidler=NULL,用它指向不同的建造者,实现修建不同的房子。
此时修建公寓和别墅两种不同房子。

int main(void)
{
    House_t *house=NULL;
    IBuilder_t *buidler=NULL;

    //指向公寓建造者,修建公寓
    buidler=(IBuilder_t*)constructor_flat_builder();
    buidler->make_door(buidler);  //修建公寓的门
    buidler->make_floor(buidler); //修建公寓的地板
    buidler->make_wall(buidler);  //修建公寓的墙
    buidler->make_window(buidler);//修建公寓的窗
    house = buidler->house;       //拿到修建的好的房子
    printf("%s\n", house->door);  //显示公寓门
    printf("%s\n", house->floor); //显示公寓地板
    printf("%s\n", house->wall);  //显示公寓墙
    printf("%s\n", house->window);//显示公寓窗
    buidler->destory(buidler);    //释放内存
    printf("\n");

    //指向别墅建造者,修建别墅
    buidler=(IBuilder_t*)constructor_villa_builder();
    buidler->make_door(buidler);    //修建别墅的门
    buidler->make_floor(buidler);   //修建别墅的地板
    buidler->make_wall(buidler);    //修建别墅的墙
    buidler->make_window(buidler);  //修建别墅的窗
    house = buidler->house;         //拿到修建好的房子
    printf("%s\n", house->door);    //显示别墅门
    printf("%s\n", house->floor);   //显示别墅地板
    printf("%s\n", house->wall);    //显示别墅墙
    printf("%s\n", house->window);  //显示别墅窗
    buidler->destory(buidler);      //释放内存

    return 0;
}

测试结果:
测试结果

四、总结

通过上面的内容,我们了解到建造者模式主要是针对创建对象的过程的。而且还可以控制一个复杂类中部件创建的顺序以及部件创建的内容。提高程序的扩展性,践行“高内聚、低耦合”。

想要整个工程文件的小伙伴:在微信公众号【Linux编程用C】,在微信公众号回复designer即可获取

我是小C,欢迎大家关注、点赞支持,我们一起交流讨论学习!

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值