工厂模式
概述:
利用实现计算器的案例实现一个简单的工厂设计模式,参考资料《大话设计模式》;
工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。
工厂方法模式是一种实现了“工厂”概念的面向对象设计模式。就像其他创建型模式一样,它也是处理在不指定对象具体类型的情况下创建对象的问题。
工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。”
工厂模式也是一种反射机制,可维护、可拓展、可复用(个人理解)。
工程结构说明:
简单说明:加、减、乘、除 都公有继承自运算类并重写基类虚函数,基类指向子类,子类重写基类虚函数此时触发多态,此案例也诠释C++封装、继承、多态的强大特性;
界面类代码:
.h:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
/**
* @brief on_pushButton_3_clicked 运算结果按钮点击事件将运算结果输出
*/
void on_pushButton_3_clicked();
private:
/**
* @brief virtualRun 获取界面数字调用运算类函数进行运算将结果输出到界面
* @return
*/
double virtualRun();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
.cpp:
#include "widget.h"
#include "ui_widget.h"
#include "OperationFactor.h"//界面类作为使用者我们只需要使用工厂类即可
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
double Widget::virtualRun()
{
Operation* pOper = OperationFactor::creatorOperation(ui->lineEdit_A->text().toDouble(),ui->lineEdit_B->text().toDouble(),ui->comboBox->currentText());
//此时基类指向子类,子类重写基类虚函数,触发多态
return pOper->GetResult();
}
void Widget::on_pushButton_3_clicked()
{
ui->label_C->setText(QString::number(virtualRun()));
}
工厂类:
.h:
#ifndef OPERATIONFACTOR_H
#define OPERATIONFACTOR_H
#include <QString>
#include <QMap>
#include "Operation.h"
#include "OperationAdd.h"
#include "OperationDiv.h"
#include "OperationMul.h"
#include "OperationSub.h"
class OperationFactor
{
public:
OperationFactor();
~OperationFactor();
/**
* @brief creatorOperation 工厂类函数
* @param numA 输入数字
* @param numB 输入数字
* @param operater 运算符号
* @return 返回继承自运算类的子对象(这样就可以条用子类函数,此时触发多态)
*/
static Operation *creatorOperation(double numA, double numB, QString operater);
//强烈建议此函数使用静态的
private:
/**
* @brief initQMap 初始化Map容器 key【QString运算符号】 value【int运算符号值】
*/
static void initQMap();
private:
static QMap<QString,int> m_Map;
};
.cpp:
#include "OperationFactor.h"
QMap<QString,int> OperationFactor::m_Map; //静态Map定义
OperationFactor::OperationFactor()
{
}
OperationFactor::~OperationFactor()
{
}
Operation *OperationFactor::creatorOperation(double numA, double numB, QString operater)
{
//创建一个函数,返回值为运算类(基类)对象
//通过基类对象获取子类对象(多个子类继承自基类)
Operation *p_Oper = NULL;
initQMap();
switch(m_Map[operater])
{
case 1:
p_Oper = new OperationAdd(numA,numB);
break;
case 2:
p_Oper = new OperationDiv(numA,numB);
break;
case 3:
p_Oper = new OperationMul(numA,numB);
break;
case 4:
p_Oper = new OperationSub(numA,numB);
break;
default:break;
}
return p_Oper;
}
void OperationFactor::initQMap()
{
m_Map.insert("+",1);
m_Map.insert("-",2);
m_Map.insert("*",3);
m_Map.insert("/",4);
}
运算类:
.h:
#ifndef OPERATION_H
#define OPERATION_H
#include <QObject>
class Operation : public QObject
{
Q_OBJECT
public:
explicit Operation(QObject *parent = 0);
~Operation();
public:
/**
* @brief GetResult 纯抽函数子类需要重写虚函数
* @return
*/
double virtual GetResult()=0;
//double virtual GetResult(){return 0;}//等价上面写法
};
#endif // OPERATION_H
.cpp:
#include "Operation.h"
Operation::Operation(QObject *parent) : QObject(parent)
{
}
Operation::~Operation()
{
}
加法类:
.h:
#ifndef OPERATIONADD_H
#define OPERATIONADD_H
#include "Operation.h"
//加法类继承自运算类
class OperationAdd : public Operation
{
public:
OperationAdd(const double &numA,const double &numB);
~OperationAdd();
public:
double GetResult();
private:
double numA;
double numB;
};
#endif // OPERATIONADD_H
.cpp:
#include "OperationAdd.h"
OperationAdd::OperationAdd(const double &numA, const double &numB)
{
this->numA = numA;
this->numB = numB;
}
OperationAdd::~OperationAdd()
{
}
double OperationAdd::GetResult()
{
double result = 0;
result = numA + numB;
return result;
}
减法类:
.h:
#ifndef OPERATIONDIV_H
#define OPERATIONDIV_H
#include "Operation.h"
class OperationDiv : public Operation
{
public:
OperationDiv(const double &numA,const double &numB);
~OperationDiv();
public:
double GetResult();
private:
double numA;
double numB;
};
#endif // OPERATIONDIV_H
.cpp:
#include "OperationDiv.h"
OperationDiv::OperationDiv(const double &numA, const double &numB)
{
this->numA = numA;
this->numB = numB;
}
OperationDiv::~OperationDiv()
{
}
double OperationDiv::GetResult()
{
double result = 0;
result = numA - numB;
return result;
}
乘法类:
.h:
#ifndef OPERATIONMUL_H
#define OPERATIONMUL_H
#include "Operation.h"
class OperationMul : public Operation
{
public:
OperationMul(const double &numA,const double &numB);
~OperationMul();
public:
double GetResult();
private:
double numA;
double numB;
};
#endif // OPERATIONMUL_H
.cpp:
#include "OperationMul.h"
OperationMul::OperationMul(const double &numA, const double &numB)
{
this->numA = numA;
this->numB = numB;
}
OperationMul::~OperationMul()
{
}
double OperationMul::GetResult()
{
double result = 0;
result = numA * numB;
return result;
}
除法类:
.h:
#ifndef OPERATIONSUB_H
#define OPERATIONSUB_H
#include "Operation.h"
class OperationSub : public Operation
{
public:
OperationSub(const double &numA,const double &numB);
~OperationSub();
public:
double GetResult();
private:
double numA;
double numB;
};
#endif // OPERATIONSUB_H
.cpp:
#include "OperationSub.h"
OperationSub::OperationSub(const double &numA, const double &numB)
{
this->numA = numA;
this->numB = numB;
}
OperationSub::~OperationSub()
{
}
double OperationSub::GetResult()
{
double result = 0;
result = numA / numB;
return result;
}
运行效果图:
概括:
1.如果后期要更改加法运算,我们只需要到加法类进行修改就可以了;
2.如果后期增加其它运算方法,那就增加相应运算子类就可以了,在工厂类的 switch 中增加分支就可以了;
3.这样后期维护或者增加功能不会前期功能有影响,要修改界面就去界面类,与其它类无关;
4.程序中需要要优化的地方是子类的成员变量可以不写直接使用基类成员变量;
over:
欢迎大家关注作者在文末评论、点赞、转发以及批评指正!
如果大家有更好的方法或有问题可以在文末评论一起讨论!
共同学习!
共同进步!
“与其多看不如多练,想啥呢?动弹呢!”
“与其思乡,不如买票回家!”