简单工厂模式(simple-factory-model)
简单工厂模式(simple-factory-model)
文章目录
- 简单工厂模式(simple-factory-model)
- 一、简单计算器的设计
- 二、面向对象介入
- 三、计算工厂
- 四、应用场景
一、简单计算器的设计
假如让你写一份简单计算器的代码,我想大部分有一定基础的人都能在五分钟之内完成以下的代码:
#include <iostream>
// simple calculator
int main() {
double x = 0, y = 0;
std::cout << "please enter two operands" << std::endl;
std::cin >> x >> y;
char opt = '+';
std::cout << "please enter the operator(+-*/)" << std::endl;
std::cin >> opt;
double res = 0;
switch (opt) {
case '+':
res = x + y;
break;
case '-':
res = x - y;
break;
case '*':
res = x * y;
break;
case '/':
if (y == 0) {
std::cout << "invalid dividend!" << std::endl;
} else {
res = x / y;
}
break;
default:
std::cout << "invalid operator!" << std::endl;
break;
}
std::cout << "res = " << res << std::endl;
}
这样的代码有哪些问题呢?
- 其一:可复用性太差。假设公司业务新增了GUI页面的计算器,那么就需要把这部分代码逻辑ctrl cv过去,从而造成代码的重复。然而编程的一大原则就是用尽可能的办法去避免重复,毕竟一旦某部分逻辑出现问题,那么在维护时就要修改所有的重复代码,这将是一场灾难。
- 其二:这样的代码仅仅是面向过程的。在C++/Java等面向对象(Object Oriented, OO)语言盛行的今天,这样一份代码没有利用封装、继承、多态的特性,这也是它难以复用、维护的根本原因。
二、面向对象介入
如何将上述代码改写成面向对象的样子呢?
class Calculator {
public:
static double get_result(double x, double y, char opt) {
double res = 0;
switch (opt) {
case '+':
res = x + y;
break;
case '-':
res = x - y;
break;
case '*':
res = x * y;
break;
case '/':
if (y == 0) {
std::cout << "invalid dividend!" << std::endl;
} else {
res = x / y;
}
break;
default:
std::cout << "invalid operator!" << std::endl;
break;
}
}
};
嗯…很好,用到了封装的特性,那么继承与多态呢?这么好的东西为什么不用呢,是不喜欢么?
ps:笔者在学习甚至在实习做项目期间都没有用到过继承多态,还是吃了学的少的亏呀。
此外,这份代码还有一种隐患:如果业务需要新增一项功能,比如开根号,那么就要在原有的代码基础上直接改,万一改错了老代码呢?当然,这里的逻辑比较简单,一般不会出错,但是在复杂的公司业务中,难免会出现新手程序员新增功能后,整个业务直接跑不起来的情况。一方面,是程序员自身的问题,另一方面,也是这份代码的可维护性不高导致的。
三、计算工厂
"operator.hpp"
#pragma once
class Operator {
public:
virtual double get_result() {};
virtual void set_operands(double x, double y) {};
};
class OperatorAdd : public Operator {
public:
double get_result() override {
return x_ + y_;
}
void set_operands(double x, double y) {
x_ = x;
y_ = y;
}
private:
double x_;
double y_;
};
class OperatorSub : public Operator {
public:
double get_result() override {
return x_ - y_;
}
void set_operands(double x, double y) {
x_ = x;
y_ = y;
}
private:
double x_;
double y_;
};
class OperatorMul : public Operator {
public:
double get_result() override {
return x_ * y_;
}
void set_operands(double x, double y) {
x_ = x;
y_ = y;
}
private:
double x_;
double y_;
};
class OperatorDiv : public Operator {
public:
double get_result() override {
return x_ / y_;
}
void set_operands(double x, double y) {
x_ = x;
y_ = y;
}
private:
double x_;
double y_;
};
operator.hpp中负责实现不同的运算类,它们继承于Operator
,用于后面的多态。
"calculator_factor.hpp"
#pragma once
#include "operator.hpp"
class CalculatorFactory {
public:
static Operator *get_calculator(char opt) {
switch (opt) {
case '+':
return new OperatorAdd;
case '-':
return new OperatorSub;
case '*':
return new OperatorMul;
case '/':
return new OperatorDiv;
}
}
};
计算工厂根据不同的操作符返回不同的运算对象。
"main.cpp"
#include <iostream>
#include <memory>
#include "calculator_factory.hpp"
// main.cpp
int main() {
double x = 0, y = 0;
std::cout << "please enter two operands" << std::endl;
std::cin >> x >> y;
char opt = '+';
std::cout << "please enter the operator(+-*/)" << std::endl;
std::cin >> opt;
// simple factory model
std::shared_ptr<Operator> opt_obj = std::shared_ptr<Operator>
(CalculatorFactory::get_calculator(opt));
opt_obj->set_operands(x, y);
std::cout << opt_obj->get_result() << std::endl;
return 0;
}
可见,在简单工厂模式的介入下,我们需要新增功能,只需要在"calculator_factor.hpp"中增加一个case,并在"operator.hpp"中新增一个运算类即可。
因此,代码的可维护性较为良好。
四、应用场景
简单工厂模式的核心在于一个根据不同的需要(参数的不同)创建不同的对象实例的工厂,但是由于每增加一个对象都要修改一次工厂类,因此该设计模式的可扩展性一般,适用于工厂生产的对象实例较少的情况。