简单工厂模式
- 加减乘除共有部分,形成基类
- 简单工厂类"知道"运算类,但是不构成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;
}