设计模式是重构的目标,它在代码复用和扩展方面有着非常重要的作用。学习面向对象,重构和设计模式的重要性自然不言而喻。那么,学习设计模式需要与软件设计,软件编码相结合起来,以例子为驱动。本文将通过MFC计算器的实现来学习简单工厂模式。
无论怎么样,首先应该抽象出MFC计算器的实体类。通过查找名词,动名词等等,准确找到实体类是第一步。
显然,它的核心实体类是Operator运算类。细想之,它的实现恰好与简单工厂密切相关。
简单工厂模式解释:
简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫静态工厂方法模式(Static FactoryMethod Pattern),是通过定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
简单工厂模式的UML图:
简单工厂模式中包含的角色及其相应的职责如下:
工厂角色(Creator):这是简单工厂模式的核心,由它负责创建所有的类的内部逻辑。当然工厂类必须能够被外界调用,创建所需要的产品对象。
抽象(Product)产品角色:简单工厂模式所创建的所有对象的父类,注意,这里的父类可以是接口也可以是抽象类,它负责描述所有实例所共有的公共接口。
具体产品(Concrete Product)角色:简单工厂所创建的具体实例对象,这些具体的产品往往都拥有共同的父类。
计算器的设计自然就出来了,请看类图。
在这里,C++语言的多态特性——父类对象指针操作子类对象。核心类是OperatorFactory 和 Operator 。以字符串传参。
下面附上关键代码和工程分享。
// CALCULATOR_MFCDlg.h : 头文件
//
#pragma once
#include <stack>
#include "afxwin.h"
//#include "Operator.h"
#include "OpertorFactory.h"
using namespace std;
// CCALCULATOR_MFCDlg 对话框
class CCALCULATOR_MFCDlg : public CDialogEx
{
// 构造
public:
CCALCULATOR_MFCDlg(CWnd* pParent = NULL); // 标准构造函数
// 对话框数据
enum { IDD = IDD_CALCULATOR_MFC_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButton0();
CEdit m_EditNumA;
CEdit m_EditOperator;
CEdit m_EditNumB;
//CString m_strNumA;
double m_NumA;
double m_NumB;
double m_Num;
double m_Result;
CString m_strTemp;
char m_Oper;
afx_msg void OnBnClickedButtonpoint();
afx_msg void OnBnClickedButtonequal();
afx_msg void OnBnClickedButton1();
afx_msg void OnBnClickedButton2();
afx_msg void OnBnClickedButton3();
afx_msg void OnBnClickedButton4();
afx_msg void OnBnClickedButton5();
afx_msg void OnBnClickedButton6();
afx_msg void OnBnClickedButton7();
afx_msg void OnBnClickedButton8();
afx_msg void OnBnClickedButton9();
afx_msg void OnBnClickedButtonadd();
afx_msg void OnBnClickedButtonsub();
afx_msg void OnBnClickedButtonmul();
afx_msg void OnBnClickedButtondiv();
afx_msg void OnBnClickedButtonclear();
double StrTempToDou();
stack<double> S_Num;
stack<char>S_Oper;
//OpertorFactory OF;
double GetFinalResult(double a,double b,char op);
void CalSNum();
void ExEOperator(char op);
};
void CCALCULATOR_MFCDlg::OnBnClickedButton0()
{
// TODO: 在此添加控件通知处理程序代码
//CString str=_T("0");
//m_EditNumA.GetWindowText(str);
m_strTemp+=_T("0");
//m_strNumA+=str;
m_EditNumA.SetWindowTextW(m_strTemp);
}
void CCALCULATOR_MFCDlg::OnBnClickedButtonpoint()
{
// TODO: 在此添加控件通知处理程序代码
m_strTemp+=_T(".");
m_EditNumA.SetWindowTextW(m_strTemp);
}
void CCALCULATOR_MFCDlg::OnBnClickedButtonequal()
{
// TODO: 在此添加控件通知处理程序代码
//OpertorFactory OF;
/*
m_NumB=StrTempToDou();
m_strTemp=_T("");
Operator* oper=NULL;
oper=OF.createOperator(m_Oper);
oper->SetNumberA(m_NumA);
oper->SetNumberB(m_NumB);
double result=oper->GetResult();
m_Result=result;
//m_NumA=m_Result;
m_strTemp.Format(_T("%.2f"),result);
m_EditNumA.SetWindowTextW(m_strTemp);
m_EditNumB.SetWindowTextW(_T(""));
*/
m_Num=StrTempToDou();
m_strTemp=_T("");
S_Num.push(m_Num);
/*
double a=S_Num.top();
S_Num.pop();
double b=S_Num.top();
S_Num.pop();
char op=S_Oper.top();
S_Oper.pop();
m_Result=GetFinalResult(a,b,op);
*/
CalSNum();
m_strTemp.Format(_T("%.2f"),m_Result);
m_EditNumA.SetWindowTextW(m_strTemp);
//clear
while(!S_Num.empty())S_Num.pop();
while(!S_Oper.empty())S_Oper.pop();
m_Result=0.0;
}
void CCALCULATOR_MFCDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
m_strTemp+=_T("1");
m_EditNumA.SetWindowTextW(m_strTemp);
}
void CCALCULATOR_MFCDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
m_strTemp+=_T("2");
m_EditNumA.SetWindowTextW(m_strTemp);
}
void CCALCULATOR_MFCDlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
m_strTemp+=_T("3");
m_EditNumA.SetWindowTextW(m_strTemp);
}
void CCALCULATOR_MFCDlg::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
m_strTemp+=_T("4");
m_EditNumA.SetWindowTextW(m_strTemp);
}
void CCALCULATOR_MFCDlg::OnBnClickedButton5()
{
// TODO: 在此添加控件通知处理程序代码
m_strTemp+=_T("5");
m_EditNumA.SetWindowTextW(m_strTemp);
}
void CCALCULATOR_MFCDlg::OnBnClickedButton6()
{
// TODO: 在此添加控件通知处理程序代码
m_strTemp+=_T("6");
m_EditNumA.SetWindowTextW(m_strTemp);
}
void CCALCULATOR_MFCDlg::OnBnClickedButton7()
{
// TODO: 在此添加控件通知处理程序代码
m_strTemp+=_T("7");
m_EditNumA.SetWindowTextW(m_strTemp);
}
void CCALCULATOR_MFCDlg::OnBnClickedButton8()
{
// TODO: 在此添加控件通知处理程序代码
m_strTemp+=_T("8");
m_EditNumA.SetWindowTextW(m_strTemp);
}
void CCALCULATOR_MFCDlg::OnBnClickedButton9()
{
// TODO: 在此添加控件通知处理程序代码
m_strTemp+=_T("9");
m_EditNumA.SetWindowTextW(m_strTemp);
}
void CCALCULATOR_MFCDlg::OnBnClickedButtonadd()
{
// TODO: 在此添加控件通知处理程序代码
/*
m_NumA=StrTempToDou();
m_strTemp+=_T("+");
m_EditNumB.SetWindowTextW(m_strTemp);
m_Oper='+';
//UpdateData(FALSE);
m_strTemp=_T("");
m_EditNumA.SetWindowTextW(m_strTemp);
S.push(m_NumA);
if(S.size==2)
{
}
*/
/*
m_Num=StrTempToDou();
m_strTemp=_T("");
S_Num.push(m_Num);
if(S_Num.size()==2)
{
/*
double A=S_Num.top();
S_Num.pop();
double B=S_Num.top();
S_Num.pop();
char op=S_Oper.top();
S_Oper.pop();
m_Result=GetFinalResult(A,B,op);
CalSNum();
S_Num.push(m_Result);
S_Oper.push('+');
}
else
{
//S_Num.push(m_Num);
S_Oper.push('+');
}
*/
ExEOperator('+');
}
void CCALCULATOR_MFCDlg::OnBnClickedButtonsub()
{
// TODO: 在此添加控件通知处理程序代码
ExEOperator('-');
}
void CCALCULATOR_MFCDlg::OnBnClickedButtonmul()
{
// TODO: 在此添加控件通知处理程序代码
ExEOperator('*');
}
void CCALCULATOR_MFCDlg::OnBnClickedButtondiv()
{
// TODO: 在此添加控件通知处理程序代码
ExEOperator('/');
}
void CCALCULATOR_MFCDlg::OnBnClickedButtonclear()
{
// TODO: 在此添加控件通知处理程序代码
//m_strTemp+=_T(".");
m_EditNumA.SetWindowTextW(_T(""));
}
double CCALCULATOR_MFCDlg::StrTempToDou()
{
double Num=0.0;//=atof(m_strTemp);
//m_strTemp.Format(_T("%.2f"),Num);
Num=_ttof(m_strTemp);
//m_strTemp=_T("");
return Num;
}
double CCALCULATOR_MFCDlg::GetFinalResult(double a,double b,char op)
{
OpertorFactory OF;
Operator* oper=NULL;
oper=OF.createOperator(op);
oper->SetNumberA(a);
oper->SetNumberB(b);
double result=oper->GetResult();
return result;
}
void CCALCULATOR_MFCDlg::CalSNum()
{
double A=S_Num.top();
S_Num.pop();
double B=S_Num.top();
S_Num.pop();
char op=S_Oper.top();
S_Oper.pop();
if(op=='+' || op=='*')
m_Result=GetFinalResult(A,B,op);
else m_Result=GetFinalResult(B,A,op);
}
void CCALCULATOR_MFCDlg::ExEOperator(char op)
{
m_Num=StrTempToDou();
m_strTemp=_T("");
S_Num.push(m_Num);
if(S_Num.size()==2)
{
/*
double A=S_Num.top();
S_Num.pop();
double B=S_Num.top();
S_Num.pop();
char op=S_Oper.top();
S_Oper.pop();
m_Result=GetFinalResult(A,B,op);
*/
CalSNum();
S_Num.push(m_Result);
S_Oper.push(op);
}
else
{
//S_Num.push(m_Num);
S_Oper.push(op);
}
}
MFC工程下载:http://download.youkuaiyun.com/detail/greenapple_shan/7735979
参考资料:程杰 《大话设计模式》