简单工厂模式(大话设计模式)C/C++版本

简单工厂模式

在这里插入图片描述

  1. 加减乘除共有部分,形成基类
  2. 简单工厂类"知道"运算类,但是不构成has-a和contains-a的语义,所以是关联。

计算器
1. input number => 易变(界面逻辑)
2. select operator => 运算符类(业务逻辑)
3. calculate => 不同运算对应不同计算方法(业务逻辑)
4. outupt result(界面逻辑)

界面输入到业务的过程 => 工厂类
2+3 => 运算类
==>
1. 业务逻辑与界面逻辑分离 => 将计算过程封装成函数 封装
2. 不同的运算符对应的不同的计算过程分离成类 => 继承共有特性 继承
3. 各运算符实现基类中的GetResult => 重写共有行为 多态

将界面逻辑的输入到业务逻辑的地方,封装成一个函数也是不错的。但是将其用类来封装更好。
类封装较于函数封装的好处:
1. 类:属性+行为;函数:行为
2. 类支持继承,更易于扩展(较于函数可以随便加属性和新的行为)
3. 封装性更好(作用域就更安全更小)
4. 面向对象编程,更有连续性,创建一个类实例后,多次使用的都是同一个实例的方法;
而函数多次调用后,连续和联系没有那么强,少了点OOP的味儿~

C++版本

参考:https://www.cnblogs.com/Galesaur-wcy/p/15926669.html

#include <iostream>
using namespace std;
// 运算类
class Operation
{
private:
	double _NumA;
	double _NumB;

public:
	void SetNumA()
	{
		cout << "Enter a double number: ";
		if (!(cin >> _NumA))
			throw "It must be a number";
	}

	double GetNumA()
	{
		return _NumA;
	}

	void SetNumB()
	{
		cout << "Enter a double number: ";
		if (!(cin >> _NumB))
			throw "It must be a number";
	}

	double GetNumB()
	{
		return _NumB;
	}

	virtual double GetResult()
	{
		int result = 0;
		return result;
	}
};

class OperationAdd : public Operation
{
public:
	double GetResult()
	{
		double result = GetNumA() + GetNumB();
		return result;
	}
};

class OperationSub : public Operation
{
public:
	double GetResult()
	{
		double result = GetNumA() - GetNumB();
		return result;
	}
};

class OperationMul : public Operation
{
public:
	double GetResult()
	{
		double result = GetNumA() * GetNumB();
		return result;
	}
};

class OperationDiv : public Operation
{
public:
	double GetResult()
	{
		if (GetNumB() == 0)
		{
			throw "The divisor cannot be 0";
		}
		double result = GetNumA() / GetNumB();
		return result;
	}
};

class OperatorFactory
{
public:
	Operation *CreatOperation(char s)
	{
		Operation *ope = nullptr;
		switch (s)
		{
		case '+':
			ope = new OperationAdd;
			break;
		case '-':
			ope = new OperationSub;
			break;
		case '*':
			ope = new OperationMul;
			break;
		case '/':
			ope = new OperationDiv;
			break;
		default:
			throw "Error input operator!";
			break;
		}
		return ope;
	}
};

int main()
{
	OperatorFactory fac;
	cout << "Choose an operation:";
	char operator_char;
	cin >> operator_char;
	try
	{
		Operation *oper = fac.CreatOperation(operator_char);
		oper->SetNumA();
		oper->SetNumB();
		cout << "result is: " << oper->GetResult() << endl;
	}
	catch (const char *err)
	{
		cerr << err << endl;
		return -1;
	}

	return 0;
}

C版本

C底层是不支持面向对象编程的(如:继承、多态),但是不是说不可以面向对象编程的。
C的结构体就是最类似class类的概念,但是不支持行为属性,只能通过回调函数,依赖倒置,将实现交给开发者。但是这也说明C中的对象的行为不是生来就有的,是需要初始化的。而且该行为的作用域也比类中行为的要大。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

typedef struct Operation
{
    double NumA;
    double NumB;
    double (*GetResult)(struct Operation *);
} Operation;

typedef struct OperationAdd
{
    Operation base; // 设置为第一个成员属性,模拟继承
} OperationAdd;

typedef struct OperationSub
{
    Operation base;
} OperationSub;

typedef struct OperationMul
{
    Operation base;
} OperationMul;

typedef struct OperationDiv
{
    Operation base;
} OperationDiv;

double OperationAddGetResult(struct Operation *op)
{
    OperationAdd *add = (OperationAdd *)op;
    return add->base.NumA + add->base.NumB;
}

double OperationSubGetResult(struct Operation *op)
{
    OperationSub *sub = (OperationSub *)op;
    return sub->base.NumA - sub->base.NumB;
}

double OperationMulGetResult(struct Operation *op)
{
    OperationMul *mul = (OperationMul *)op;
    return mul->base.NumA * mul->base.NumB;
}

double OperationDivGetResult(struct Operation *op)
{
    OperationDiv *div = (OperationDiv *)op;
    if (div->base.NumB == 0)
    {
        fputs("The divisor cannot be 0\n", stderr);
        exit(EXIT_FAILURE);
    }
    return div->base.NumA / div->base.NumB;
}

Operation *CreateOperation(char op)
{
    Operation *ope = NULL;
    switch (op)
    {
    case '+':
        ope = malloc(sizeof(OperationAdd));
        ope->GetResult = OperationAddGetResult;
        break;
    case '-':
        ope = malloc(sizeof(OperationSub));
        ope->GetResult = OperationSubGetResult;
        break;
    case '*':
        ope = malloc(sizeof(OperationMul));
        ope->GetResult = OperationMulGetResult;
        break;
    case '/':
        ope = malloc(sizeof(OperationDiv));
        ope->GetResult = OperationDivGetResult;
        break;
    default:
        fputs("Error input operator!\n", stderr);
        return NULL;
    }
    return ope;
}

void SetNumA(Operation *ope)
{
    printf("Enter a double number: ");
    if (scanf("%lf", &ope->NumA) != 1)
    {
        fputs("It must be a number\n", stderr);
        exit(EXIT_FAILURE);
    }
}

void SetNumB(Operation *ope)
{
    printf("Enter a double number: ");
    if (scanf("%lf", &ope->NumB) != 1)
    {
        fputs("It must be a number\n", stderr);
        exit(EXIT_FAILURE);
    }
}

int main()
{
    printf("Choose an operation: ");
    char operator_char = getchar();

    Operation *oper = CreateOperation(operator_char);
    if (!oper)
        return EXIT_FAILURE;

    SetNumA(oper);
    SetNumB(oper);
    printf("Result is: %f\n", oper->GetResult(oper));

    free(oper);
    return 0;
}

在前一版的基础上,将SetNumA和SetNumB设置为Operation类(结构体)的行为,代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

typedef struct Operation
{
    double NumA;
    double NumB;
    double (*GetResult)(struct Operation *);
    void (*SetNumA)(struct Operation *);
    void (*SetNumB)(struct Operation *);
} Operation;

typedef struct OperationAdd
{
    Operation base; // 设置为第一个成员属性,模拟继承
} OperationAdd;

typedef struct OperationSub
{
    Operation base;
} OperationSub;

typedef struct OperationMul
{
    Operation base;
} OperationMul;

typedef struct OperationDiv
{
    Operation base;
} OperationDiv;

double OperationAddGetResult(struct Operation *op)
{
    OperationAdd *add = (OperationAdd *)op;
    return add->base.NumA + add->base.NumB;
}

double OperationSubGetResult(struct Operation *op)
{
    OperationSub *sub = (OperationSub *)op;
    return sub->base.NumA - sub->base.NumB;
}

double OperationMulGetResult(struct Operation *op)
{
    OperationMul *mul = (OperationMul *)op;
    return mul->base.NumA * mul->base.NumB;
}

double OperationDivGetResult(struct Operation *op)
{
    OperationDiv *div = (OperationDiv *)op;
    if (div->base.NumB == 0)
    {
        fputs("The divisor cannot be 0\n", stderr);
        exit(EXIT_FAILURE);
    }
    return div->base.NumA / div->base.NumB;
}

void SetNumA(Operation *ope)
{
    printf("Enter a double number: ");
    if (scanf("%lf", &ope->NumA) != 1)
    {
        fputs("It must be a number\n", stderr);
        exit(EXIT_FAILURE);
    }
}

void SetNumB(Operation *ope)
{
    printf("Enter a double number: ");
    if (scanf("%lf", &ope->NumB) != 1)
    {
        fputs("It must be a number\n", stderr);
        exit(EXIT_FAILURE);
    }
}

Operation *CreateOperation(char op)
{
    Operation *ope = NULL;
    switch (op)
    {
    case '+':
        ope = malloc(sizeof(OperationAdd));
        ope->GetResult = OperationAddGetResult;
        break;
    case '-':
        ope = malloc(sizeof(OperationSub));
        ope->GetResult = OperationSubGetResult;
        break;
    case '*':
        ope = malloc(sizeof(OperationMul));
        ope->GetResult = OperationMulGetResult;
        break;
    case '/':
        ope = malloc(sizeof(OperationDiv));
        ope->GetResult = OperationDivGetResult;
        break;
    default:
        fputs("Error input operator!\n", stderr);
        return NULL;
    }
    ope->SetNumA = SetNumA;
    ope->SetNumB = SetNumB;
    return ope;
}

int main()
{
    printf("Choose an operation: ");
    char operator_char = getchar();

    Operation *oper = CreateOperation(operator_char);
    if (!oper)
        return EXIT_FAILURE;

    oper->SetNumA(oper);
    oper->SetNumB(oper);
    printf("Result is: %f\n", oper->GetResult(oper));

    free(oper);
    return 0;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值