vlambda博客
学习文章列表

C语言设计模式--原型模式

模式动机

原型模式的简单程度仅次于单例模式和迭代器模式。正是由于简 单,使用的场景才非常地多。它的主要功能是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

简单来说呢,就是利用当前结构体来复制出一个新的结构体。就比如说有一份word文档,它本身是一个对象,但是我可以利用这份文档通过不断地进行复制粘贴,从而得到很多新的一模一样的文档,每一份文档都是一个新的对象。如下图

举个例子,我现在要去投简历面试,然后需要事先准备了3份完全一样的简历。

传统代码实现:

#include <stdio.h> typedef struct Resume   {      char* name;    char* sex;    int age; }s_resume; void main() {  s_resume *info1,*info2,*info3;    /*构造第一份简历*/  info1 = (s_resume*)malloc(sizeof(s_resume));    info1->name = "皮特";  info1->sex = "男";  info1->age = 20;  printf("这是%s的简历,性别为%s,年龄%d\n",info1->name,info1->sex,info1->age);    /*构造第二份简历*/  info2 = (s_resume*)malloc(sizeof(s_resume));  info2->name = "皮特";  info2->sex = "男";  info2->age = 20;  printf("这是%s的简历,性别为%s,年龄%d\n",info2->name,info2->sex,info2->age);    /*构造第三份简历*/  info3 = (s_resume*)malloc(sizeof(s_resume));  info3->name = "皮特";  info3->sex = "男";  info3->age = 20;  printf("这是%s的简历,性别为%s,年龄%d\n",info3->name,info3->sex,info3->age); } }

代码可以直接复制粘贴在菜鸟 C 在线工具运行(https://c.runoob.com/compile/11)中查看运行结果。结果如下:

这是皮特的简历,性别为男,年龄20
这是皮特的简历,性别为男,年龄20
这是皮特的简历,性别为男,年龄20

我们看下这样做法的弊端:

  • 三份简历需要三次同样的手动初始化,非常麻烦,如果需要几十分、上百份,代码非常臃肿丑陋。

  • 如果一旦简历的内容发生了变化,那么需要逐份去修改,效率极低。

解决方案

使用原型模式,增加一个复制接口,充分利用现有的对象来复制其他的对象,从而减化对象的初始化过程。代码注释非常清晰地展示了思路过程。

原型模式代码实现:

#include <stdio.h> typedef struct Resume   {      char* name;    char* sex;    int age;    /*增加复制接口*/    struct Resume* (*copy) (struct Resume* pData); }s_resume; /*复制接口实现*/ struct Resume* Resume_copy(struct Resume* pData)   {      s_resume* pResult = (s_resume*)malloc(sizeof(s_resume));      memmove(pResult, pData, sizeof(s_resume));      return pResult;   }; void main() {  s_resume *info1,*info2,*info3;    /*构造第一份简历*/  info1 = (s_resume*)malloc(sizeof(s_resume));    info1->name = "皮特";  info1->sex = "男";  info1->age = 20;  info1->copy = Resume_copy;  printf("这是%s的简历,性别为%s,年龄%d\n",info1->name,info1->sex,info1->age);    /*构造第二份简历*/  info2 = info1->copy(info1);  printf("这是%s的简历,性别为%s,年龄%d\n",info2->name,info2->sex,info2->age);    /*构造第三份简历*/  info3 = info1->copy(info1);  printf("这是%s的简历,性别为%s,年龄%d\n",info3->name,info3->sex,info3->age); }

代码可以直接复制粘贴在菜鸟 C 在线工具运行(https://c.runoob.com/compile/11)中查看运行结果。结果如下:

这是皮特的简历,性别为男,年龄20
这是皮特的简历,性别为男,年龄20
这是皮特的简历,性别为男,年龄20

原型模式性能优良,通过内存二进制流的拷贝,要比频繁手动地初始化一个对象开销低很多。尤其是要在产生大量的对象时,原型模式可以更好地体现其优点。

不过在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过copy的方法创建一个对象,然后由工厂方法提供给调用者。