• 代码的工厂模式


    概念:

    代码的工厂模式是一种设计模式,用于创建对象实例而无需直接调用构造函数。它提供了一种更加灵活和可维护的方式来创建对象,尤其是在需要根据不同情况创建不同类型的对象时非常有用。工厂模式隐藏了对象的创建细节,使代码更加模块化和可扩展。

     包括的关键元素:

    1. 工厂方法(Factory Method):这是一个方法或函数,负责创建对象实例。工厂方法通常接受一些参数,根据这些参数来确定应该创建哪种类型的对象。

    2. 产品(Product):产品是工厂方法创建的对象实例。产品通常是某个类的实例。

    3. 具体工厂(Concrete Factory):具体工厂是实际执行对象创建的类或函数。每个具体工厂通常负责创建特定类型的产品。

    4. 具体产品(Concrete Product):具体产品是由具体工厂创建的对象实例,它们是产品的具体实现。

     工厂模式的主要优点:

    1. 封装对象创建过程:工厂模式将对象的创建逻辑封装在一个函数或类中,使客户端代码无需关心对象的具体创建方式。这可以减少代码的重复性,提高代码的可维护性和可读性。

    2. 灵活性:通过工厂模式,可以轻松地更改对象的创建方式,例如切换到不同的实现类或版本,而无需修改大量客户端代码。

    3. 解耦合:工厂模式有助于减少类之间的直接依赖关系。客户端代码不需要了解对象的具体类,只需与工厂接口或函数交互。这降低了耦合度,使系统更容易维护和扩展。

    4. 单一职责原则:工厂模式有助于遵循单一职责原则,因为它将对象的创建职责从客户端代码中分离出来,并将其委托给专门的工厂类或函数。

    5. 代码组织:工厂模式可以帮助组织代码,将对象创建逻辑集中在一个地方,使代码更加结构化和清晰。

    6. 测试和调试:工厂模式使得在单元测试中更容易替换模拟对象,从而更容易进行单元测试和调试。

    总之,工厂模式是一种设计模式,有助于提高代码的可维护性、可扩展性和可测试性,同时降低了代码的耦合度,是面向对象编程中常用的一种设计方法之一。

    代码案例: 

     源代码:

    1. #include
    2. struct Animal
    3. {
    4. char name[128];
    5. int age;
    6. int sex;
    7. int others;
    8. void (*peat)();
    9. void (*pbeat)();
    10. void (*test)();
    11. };
    12. void dogEat()
    13. {
    14. printf("狗吃屎\n");
    15. }
    16. void catEat()
    17. {
    18. printf("猫吃鱼\n");
    19. }
    20. void personEat()
    21. {
    22. printf("人吃米\n");
    23. }
    24. /
    25. void dogBeat()
    26. {
    27. printf("狗咬你\n");
    28. }
    29. void catBeat()
    30. {
    31. printf("猫咬你\n");
    32. }
    33. void personBeat()
    34. {
    35. printf("人打你\n");
    36. }
    37. int main()
    38. {
    39. struct Animal dog = {
    40. .peat = dogEat,
    41. .pbeat = dogBeat,
    42. };
    43. struct Animal cat = {
    44. .peat = catEat,
    45. .pbeat = catBeat,
    46. };
    47. struct Animal person = {
    48. .peat = personEat,
    49. .pbeat = personBeat,
    50. };
    51. dog.peat();
    52. cat.peat();
    53. person.peat();
    54. dog.pbeat();
    55. cat.pbeat();
    56. person.pbeat();
    57. return 0;
    58. }

    工厂模式之后:

    自行分开成一个个子文件

    1. #include
    2. // 定义动物结构体
    3. struct Animal
    4. {
    5. char name[128];
    6. int age;
    7. int sex;
    8. int others;
    9. void (*eat)();
    10. void (*beat)();
    11. };
    12. // 定义不同类型的吃函数
    13. void dogEat()
    14. {
    15. printf("狗吃屎\n");
    16. }
    17. void catEat()
    18. {
    19. printf("猫吃鱼\n");
    20. }
    21. void personEat()
    22. {
    23. printf("人吃米\n");
    24. }
    25. // 定义不同类型的打函数
    26. void dogBeat()
    27. {
    28. printf("狗咬你\n");
    29. }
    30. void catBeat()
    31. {
    32. printf("猫咬你\n");
    33. }
    34. void personBeat()
    35. {
    36. printf("人打你\n");
    37. }
    38. // 创建动物工厂函数
    39. struct Animal createAnimal(void (*eatFunc)(), void (*beatFunc)())
    40. {
    41. struct Animal animal;
    42. animal.eat = eatFunc;
    43. animal.beat = beatFunc;
    44. return animal;
    45. }
    46. int main()
    47. {
    48. // 使用工厂函数创建不同类型的动物对象
    49. struct Animal dog = createAnimal(dogEat, dogBeat);
    50. struct Animal cat = createAnimal(catEat, catBeat);
    51. struct Animal person = createAnimal(personEat, personBeat);
    52. // 调用动物对象的方法
    53. dog.eat();
    54. cat.eat();
    55. person.eat();
    56. dog.beat();
    57. cat.beat();
    58. person.beat();
    59. return 0;
    60. }

    在上面的代码中,我们创建了一个createAnimal函数,它接受两个函数指针作为参数,并返回一个初始化好的动物对象。然后,在main函数中,我们使用createAnimal函数来创建不同类型的动物对象,然后调用它们的吃和打方法。这样就实现了工厂模式,使得创建和使用不同类型的动物对象更加灵活和可维护。

    如何理解这个模式的关键点:

    1. 抽象对象类型:在代码中,抽象对象类型是struct Animal,它定义了动物对象的通用属性和行为。这个抽象类型充当了工厂模式中的产品。

    2. 具体对象类型:不同种类的动物(狗、猫、人)被表示为具体对象类型,每个具体对象类型都有不同的实现,包括吃和打两个行为。这些具体对象类型充当了工厂模式中的具体产品。

    3. 工厂函数createAnimal函数是工厂函数,它接受不同的参数(吃和打的函数指针)来创建不同类型的动物对象。这个工厂函数充当了工厂模式中的工厂,它负责创建具体产品。

    4. 客户端代码:在main函数中,客户端代码使用工厂函数来创建不同类型的动物对象,而不需要知道如何构造这些对象的细节。客户端只关心如何使用这些对象,而不关心它们的创建过程。

     用链表写法太麻烦,也发出来吧。

    1. #include <stdio.h>
    2. #include <string.h>
    3. #include <stdlib.h>
    4. // 定义动物结构体
    5. struct Animal
    6. {
    7. char name[128]; // 动物的名字
    8. void (*peat)(); // 吃的行为函数指针
    9. void (*pbeat)(); // 攻击的行为函数指针
    10. struct Animal *next; // 指向下一个动物的指针
    11. };
    12. // dog
    13. void dogEat()
    14. {
    15. printf("狗吃屎\n");
    16. }
    17. void dogBeat()
    18. {
    19. printf("狗咬你\n");
    20. }
    21. struct Animal dog = {
    22. .name = "Pike",
    23. .peat = dogEat,
    24. .pbeat = dogBeat,
    25. .next = NULL
    26. };
    27. // cat
    28. void catEat()
    29. {
    30. printf("猫吃鱼\n");
    31. }
    32. void catBeat()
    33. {
    34. printf("猫咬你\n");
    35. }
    36. struct Animal cat = {
    37. .name = "Tom",
    38. .peat = catEat,
    39. .pbeat = catBeat,
    40. .next = NULL
    41. };
    42. // person
    43. void personEat()
    44. {
    45. printf("人吃米\n");
    46. }
    47. void personBeat()
    48. {
    49. printf("人打你\n");
    50. }
    51. struct Animal person = {
    52. .name = "Lihua",
    53. .peat = personEat,
    54. .pbeat = personBeat,
    55. .next = NULL
    56. };
    57. // 向链表中添加动物
    58. struct Animal *putAnimal(struct Animal *phead, struct Animal *animal)
    59. {
    60. if (phead == NULL)
    61. {
    62. phead = animal;
    63. }
    64. else
    65. {
    66. animal->next = phead;
    67. phead = animal;
    68. }
    69. return phead;
    70. }
    71. // 根据名字查找动物
    72. struct Animal *findName(char *str, struct Animal *phead)
    73. {
    74. struct Animal *tmp = phead;
    75. if (phead == NULL)
    76. {
    77. return NULL;
    78. }
    79. else
    80. {
    81. while (tmp != NULL)
    82. {
    83. if (strcmp(tmp->name, str) == 0)
    84. {
    85. return tmp;
    86. }
    87. tmp = tmp->next;
    88. }
    89. }
    90. return NULL;
    91. }
    92. int main()
    93. {
    94. char buf[128] = {'\0'};
    95. struct Animal *phead = NULL;
    96. struct Animal *ptmp;
    97. // 向链表中添加动物
    98. phead = putAnimal(phead, &dog);
    99. phead = putAnimal(phead, &cat);
    100. phead = putAnimal(phead, &person);
    101. while (1)
    102. {
    103. printf("请输入:Pike、Tom、Lihua\n");
    104. scanf("%s", buf);
    105. struct Animal *ptmp = findName(buf, phead);
    106. if (ptmp != NULL)
    107. {
    108. printf("姓名:%s\n", ptmp->name);
    109. ptmp->peat();
    110. ptmp->pbeat();
    111. }
    112. memset(buf, '\0', sizeof(buf));
    113. }
    114. return 0;
    115. }

  • 相关阅读:
    基于Struts开发物流配送(快递)管理系统
    C++ LibCurl实现Web隐藏目录扫描
    VBS脚本、BAT批处理脚本大公开,功能强大,简单易用 —— 定时执行专家
    蒂姆·库克喜提《时代》杂志2022百大影响力人物封面,谷爱凌、杨紫琼也入选
    chales 重写/断点/映射/手机代理/其他主机代理
    服务器常用端口号及作用
    【项目】5.1阻塞和非阻塞、同步和异步 5.2Unix、Linux上的五种IO模型
    LLM学习笔记-4
    npm install 报错常见的解决方法
    2022年暑期及9月份CSP-J1 CSP-S1初赛 培训计划及学习要点
  • 原文地址:https://blog.csdn.net/Good_go/article/details/133466193