《大话设计模式》笔记——简单工厂模式

前言

我(长胖的阿诏)是新入行的嵌入式程序员,所以用C语言做示例演示,我看到书上都是 C# 语言的代码,所以我只能先领会精神,再通过C语言复刻。在我的资源里好像没有见过用24k纯C语言来描述设计模式的例子的,所以我只能摸石头过河,如果有大牛看见我的 错误 还请劳烦指出,阿诏先行谢过。

这是同步更新的Gitee地址用于存放写过的源码文件:
https://gitee.com/auyvjpz/design-mode-notes.git


简单工厂模式

"我"的理解

简单工厂模式,顾名思义通过一个“工厂”可以生产出不同的用途的“东西”。

通过编写计算器时,我们需要面对多种计算方法的实现(加、减、乘、除等)。这时最直接的想法是通过switch去选择计算的模式,但是这样写会造成每种计算的代码耦合在一个switch的case组合中,只能说可以实现但是复用性不高。

而简单工厂模式抽象出一个“简单工厂的功能层”,通过“工厂”可以创建不同算法但执行过程相同的“功能对象”,从而应对不同计算方法的实现过程。

UML图解

OperationFactory依赖TOperation的子类创建不同TOperation功能对象

在这里插入图片描述

代码实现

// 简单工厂.c


//~~~~ 运算类 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

typedef enum TOperationTypeTag TOperationType;
enum TOperationTypeTag
{
    kOptAdd,
    kOptSub,
    kOptMul,
    kOptDiv,
}; ///< 每种计算符号枚举值

// 计算函数类型
typedef float (*TDoCalculate)(TOperation* AObj)

typedef struct 
{
    float        number1;  // 参与计算参数1
    float        number2;  // 参与计算参数2

    // 每个子类要实现的函数
    TDoCalculate __DoCalculate; 
} TOperation;

// 调用计算函数
float TOperationDoCalculate(TOperation* AObj)
{
    return AObj->__DoCalculate(AObj);
}

// 释放计算类
void TOperationFree(TOperation* AObj)
{
    if (AObj != NULL)
        free(AObj);
}

//~~~~~~~~~~~~~~~~~ 加法运算类 ~~~~~~~~~~~~~~~~~~~~~~~~~

typedef struct 
{
    TOperation parent;  // 继承计算父类
} TAddOperation;

static float L_AddDoCalculate(TOperation* AObj)
{
    return AObj->number1 + AObj->number2;
}

void* TAddOperationCreate()
{
    TAddOperation* obj = (TAddOperation*)malloc(sizeof(TAddOperation));
    
    if (obj != NULL)
        obj->__DoCalculate = L_AddDoCalculate;
    
    return (void*)obj;
}

//~~~~~~~~~~~~~~~~~ 减法运算类 ~~~~~~~~~~~~~~~~~~~~~~~~~

typedef struct 
{
    TOperation parent;  // 继承计算父类
} TSubOperation;

static float L_SubDoCalculate(TOperation* AObj)
{
    return AObj->number1 - AObj->number2;
}

void* TSubOperationCreate()
{
    TSubOperation* obj = (TSubOperation*)malloc(sizeof(TSubOperation));
    
    if (obj != NULL)
        obj->__DoCalculate = L_SubDoCalculate;
    
    return (void*)obj;
}

//~~~~~~~~~~~~~~~~~ 乘法运算类 ~~~~~~~~~~~~~~~~~~~~~~~~~

typedef struct 
{
    TOperation parent;  // 继承计算父类
} TMulOperation;

static float L_MulDoCalculate(TOperation* AObj)
{
    return AObj->number1 * AObj->number2;
}

void* TMulOperationCreate()
{
    TMulOperation* obj = (TMulOperation*)malloc(sizeof(TMulOperation));
    
    if (obj != NULL)
        obj->__DoCalculate = L_MulDoCalculate;
    
    return (void*)obj;
}

//~~~~~~~~~~~~~~~~~ 除法运算类 ~~~~~~~~~~~~~~~~~~~~~~~~~

typedef struct 
{
    TOperation parent;  // 继承计算父类
} TDivOperation;

static float L_DivDoCalculate(TOperation* AObj)
{
    return AObj->number1 / AObj->number2;
}

void* TDivOperationCreate()
{
    TDivOperation* obj = (TDivOperation*)malloc(sizeof(TDivOperation));
    
    if (obj != NULL)
        obj->__DoCalculate = L_DivDoCalculate;
    
    return (void*)obj;
}

//~~~~~~~~~~~~~~~~~ 运算工厂 ~~~~~~~~~~~~~~~~~~~~~~~~~

// 因为工厂只有一个create方法,所以可以直接以一个函数的形式存在
TOperation* OperationFactoryCreateOperation(int type)
{
    TOperation* result = NULL;
    
    switch (type)
    {
    case kOptAdd : 
        result = TAddOperationCreate();
        break;
    
    case kOptSub : 
        result = TSubOperationCreate();
        break;
    
    case kOptMul : 
        result = TMulOperationCreate();
        break;
    
    case kOptDiv : 
        result = TDivOperationCreate();
        break;  
        
    default :
        printf("暂不支持 %s 计算\n", GetOptTypeName(type));
    }
    
    return result;
}


//~~~~~~~~~~~~~~~~~ 使用示例 ~~~~~~~~~~~~~~~~~~~~~~~~~

int Test()
{

    // 选择计算方式
    TOperationType sign = InputOptType();
    // 创建对应计算对象
    TOperation* opt_obj = OperationFactoryCreateOperation(sign);
    
    if (opt_obj != NULL)
    {   
        opt_obj->number1 = InputFloat();  // 获取参数1
        opt_obj->number2 = InputFloat();  // 获取参数2
        
        float ret = TOperationDoCalculate(opt_obj);  // 得到计算结果
        printf("结果为:%f\n", ret);
        
        TOperationFree(opt_obj);  // 释放对象
    }   
    
    return 0;
}

总结

Q: 明明可以简单的用switch用5分钟写完,为什么花半小时敲这么多。

  • 首先,这样代码的层次感很强,用户(test函数编写者)只需要按照步骤一步步完成功能的实现。

  • 其次,如果需要修改某个计算可以很快的锁定需要改动的位置,修改完成后主函数不需要变动。

  • 然后,代码拓展性高,比如添加一个幂次的操作,只需要按照相同的方法复制一个子类即可,然后只在“工厂”中添加一条生产线(case 分支)即可,主函数依旧不需要动。

由此可知,简单工厂抽象了对象的行为,通过“工厂”的方式生产出具有不同行为的对象(这可能就是 多态 ),来执行相同的流程,得到不同的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值