设计模式——简单工厂模式


很多人说C语言是面向过程的编程语言,但其实准确些说,面向过程和面向对象只是一种编程思想,而不是编程语言的种类。C语言只是不太友好的面向对象的编程语言。

概述

实现思想

工厂模式多数情况下都是应用于JAVA中,但是在C中也可以实现。
通过代码编写练习后,感觉就像是一个大厂里边有好多部门,他们有一些共同的特征(结构体),而每一个部门下面又会有好多员工,他们的每一种特征又会有属于自己的属性(结构体创建的实例)。
在这里插入图片描述
官方一点的说法就是这样:

  1. Factory(工厂):核心部分,负责实现创建所有产品的内部逻辑,工厂类可以被外界直接调用,创建所需对象
  2. Product(抽象类产品):工厂类所创建的所有对象的父类,封装了产品对象的公共方法,所有的具体产品为其子类对象
  3. ConcreteProduct(具体产品):简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例。它要实现抽象产品中声明的抽象方法(有关抽象类)

在编写程序的时候要,一人一个文件来编写,用到谁就把谁拿出来。

简单工厂模式的优点

  1. 工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责
  2. 客户端无需知道所创建具体产品的类名,只需知道参数即可
  3. 也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类。(这也是我在开始的披萨店里遇到没有的披萨的解决情况)

简单工厂模式的缺点

  1. 工厂类集中了所有产品的创建逻辑,职责过重,一旦异常,整个系统将受影响
  2. 使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
  3. 系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂
  4. 简单工厂模式使用了static工厂方法,造成工厂角色无法形成基于继承的等级结构。

简单工厂模式的适用环境

  1. 工厂类负责创建对的对象比较少,因为不会造成工厂方法中的业务逻辑过于复杂

  2. 客户端只知道传入工厂类的参数,对如何创建对象不关心

demo

下面是自己编写的一段demo来模拟一下下智能家居:

主程序main.c

#include "light.h"
#include "tool.h"

int main()
{
    char cmd[30];
    struct light* phead = NULL;
    struct light* tmp = NULL;
    
    phead = put_bedroomLight_in_link(phead);
    if(phead != NULL)
        printf("%s is already!\n",phead->name);
    phead = put_sittingroomLight_in_link(phead);
    if(phead != NULL)
        printf("%s is already!\n",phead->name);
    phead = put_kitchenLight_in_link(phead); 
    if(phead != NULL)
        printf("%s is already!\n",phead->name);
    
    while(1){
        tmp = phead;
        memset(cmd,0,sizeof(char));
        printf("\n---------------------------------------------------------\n\n");
        scanf("%s",cmd);
        tmp = findByName(phead,cmd);
        if(tmp != NULL)
        {
            tmp->lightOn();                                                                                                                      
            tmp->lightOff();
        }
    }
}

(部门)light.h:

#ifndef __LIGHT_H__
#define __LIGHT_H__

#include <stdio.h>

struct light* put_bedroomLight_in_link(struct light* phead);
struct light* put_sittingroomLight_in_link(struct light* phead);
struct light* put_kitchenLight_in_link(struct light* phead);                                                                                     

struct light {
    char name[30];
    int no; 
    void (*lightOn)();
    void (*lightOff)();
    struct light* next;
};

#endif

light部门下的员工:

bedroomLight:

#include "light.h"

void bedroom_light_on()
{
    printf("bedroom light on!\n");
}

void bedroom_light_off()
{
    printf("bedroom light off!\n");
}

struct light bedroom_light = { 
    .name = "bedroomLight",
    .lightOn = bedroom_light_on,
    .lightOff = bedroom_light_off,
};

struct light* put_bedroomLight_in_link(struct light* phead)
{
    if(phead == NULL)
     {
        phead = &bedroom_light;
        return phead;
    }
    else
    {                                                                                                                                            
        bedroom_light.next = phead;
        phead = &bedroom_light;
        return phead;
    }
}

kitchenLight

#include "light.h"

void kitchen_light_on()
{
    printf("kitchen light on!\n");
}

void kitchen_light_off()
{
    printf("kitchen light off!\n");
}

struct light kitchen_light = { 
    .name = "kitchenLight",
    .lightOn = kitchen_light_on,
    .lightOff = kitchen_light_off
};

struct light* put_kitchenLight_in_link(struct light* phead)
{
    if(phead == NULL)
    {   
        phead = &kitchen_light;
        return phead;
    }   
    else
    {   
        kitchen_light.next = phead;                                                                                                              
        phead = &kitchen_light;
        return phead;
    }   
}

sittingroomLight

#include "light.h"

void sittingroom_light_on()
{
    printf("sittingroom light on!\n");
}

void sittingroom_light_off()
{
    printf("sittingroom light off!\n");
}

struct light sittingroom_light = { 
    .name = "sittingroomLight",
    .lightOn = sittingroom_light_on,
    .lightOff = sittingroom_light_off
};

struct light* put_sittingroomLight_in_link(struct light* phead)
{
    if(phead == NULL)
    { 
        phead = &sittingroom_light;
        return phead;
    }
    else
    {                                                                                                                                            
        sittingroom_light.next = phead;
        phead = &sittingroom_light;
        return phead;
    } 
}

还有我自己写的一个功能函数库

#ifndef __TOOL_H__
#define __TOOL_H__

#include <stdio.h>
#include "light.h"
#include <string.h>

struct light* findByName(struct light* phead,char* str)
{
    struct light* temp = phead;
    
    if(temp == NULL)
    {   
        printf("Init is null!\n");
        return NULL;
    }   
    else
    {   
        while(temp != NULL)
        {   
            if(strcmp(temp->name,str) == 0)
            {                                                                                                                                    
                printf("Function is already!\n");
                return temp;
            }
            temp = temp->next;
        }   
    } 
}
#endif

运行结果:
在这里插入图片描述

总结以下自己在编写这个demo时候遇到的一些问题吧:

  1. 当时自己在编写库函数的时候没有加#ifndef、#define、#endif,结果报了一些函数没有定义的错误
  2. 在各个员工初始化自己结构体中(部分)属性的时候,写的成员函数不用放在”部门“的库中,只有那些静态函数(功能函数需要放在”部门“的库中提前声明)
  3. 因为自己太久不做数据结构的题了,链表在使用的时候,总忘记声明一个临时变量来表示一下头指针
  4. 在更新新的”员工“的时候,只需要在工程文件中,复制粘贴一份已有的”员工“,直接进行修改代码即可

这样写完的代码,耦合度会比较低,而且易更改,逻辑比较清晰。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值