简单工厂模式——MFC计算器实现

设计模式是重构的目标,它在代码复用和扩展方面有着非常重要的作用。学习面向对象,重构和设计模式的重要性自然不言而喻。那么,学习设计模式需要与软件设计,软件编码相结合起来,以例子为驱动。本文将通过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.csdn.net/detail/greenapple_shan/7735979

参考资料:程杰 《大话设计模式》

简单工厂模式——MFC计算器实现

时间: 2024-10-16 00:50:31

简单工厂模式——MFC计算器实现的相关文章

(二)设计模式之PHP项目应用(简单工厂模式:计算器)

1 简单工厂模式简介 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例. 2 模式组成 1)工厂(Creator)角色 简单工厂模式的核心,它负责实现创建所有实例的内部逻辑.工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象. 2)抽象产品(Product)角色 简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口. 3)具体产品(Concrete Product)角色 是简单工厂模式的创建目标,所

简单工厂模式_计算器实现

优点: 1.不用自己再去new对象,工厂会根据给的标识,自动替你new出一个你想要的实现类对象. 2.一定程度上在加减乘除之间实现了解耦合.提高了代码的复用性和扩展性. 一.整体思想图: 二.代码实现 2.1 父类 package com.design.bean; /** * 简单工厂模式--父类(抽取固定模块) * @author phoebe * */ public class CaculateBean { private double a; private double b; privat

简单工厂模式的C++实现

用简单工厂模式实现一个计算器类: 1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Operation 7 { 8 public: 9 Operation(double numA = 0, int numB = 0) : numberA(numA), numberB(numB) 10 { 11 } 12 virtual ~Operation() 13 { 14 cout <

设计模式—简单工厂模式

设计模式之简单工厂模式 看书学习设计模式,书本来源<大话设计模式>,啃一啃怎么样设计程序 在"大话"这本书中写简单工厂模式用计算器为例来说明,其实是最简单的面向接口的编程思维,不依赖与具体的实现,而重点考虑接口.这是比较重要的思维上的转变. 重点: 1.通过继承,造成多态属性,然后在子类中实现父类的接口,在不同的子类中进行不同的接口实现.直接调用实现的接口方法得到最后的值,这一种思维够趣味 2.做增量,尽量不修改之前的,靠增加代码来更改需求 3.最通俗的说法,高内聚,低耦合

【iOS开发系列】用简单工厂模式理解OC反射机制

// 在iOS开发中,简单工厂模式使用得并不多.但是.我认为这是OC反射机制很好的一个例子, // 所以本文将以计算器为例,讲解简单工厂模式和OC的反射机制. // [简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类( // 这些产品类继承自一个父类或接口)的实例.该模式中包含的角色及其职责:工厂角色.抽 // 象产品角色.具体产品角色] // --百度百科 简单工厂模式 // 上面这句话可能不怎么好理解,我在网上找到了一个例子,可能例子本身不能完全解释这个 // 设

简单工厂模式 - 怎样实现高逼格的计算器(C#)

1. 面向过程的计算器 static void Main(string[] args) { //面向过程的计算器 try { Console.WriteLine("请输入数字A: "); string strNumA = Console.ReadLine(); Console.WriteLine("请选择运算符号(+.-.*./): "); string strOperate = Console.ReadLine(); Console.WriteLine("

学习大话设计模式01_简单工厂模式(简易计算器)

1 /** 2 * 面向对象(运算类) 3 * 简易计算器 4 * @author Monica 5 * 6 */ 7 public class Operation { 8 private double numberA = 0; 9 private double numberB = 0; 10 11 //虚函数 12 public double GetResult() { 13 double result = 0; 14 return result; 15 } 16 17 public doub

[Python设计模式] 第1章 计算器——简单工厂模式

写在前面的话 """ 读书的时候上过<设计模式>这一门课,当时使用的教材是程杰老师的<大话设计模式>,使用的语言是C#,学过课程之后初期深感面向对象思想的伟大,但是很少应用到实际开发中.后来我接触了Python,现在工作中用到最多的也是Python,或许是因为Python的便利性,我写的很多脚本/程序都还是面向过程编程,缺少面向对象的思想在里边.因此,我打算重读程杰老师的<大话设计模式>并用Python进行实践. ""&

简单工厂模式

目前正在看<大话设计模式>,写此系列的文章记录下学习的经过. 简单工厂模式 先看如下代码,使用面向对象的原理实现计算器功能 Operation运算类 1 public class Operation 2 { 3 private double numberA = 0; 4 private double numberB = 0; 5 6 public double NumberA 7 { 8 get { return numberA; } 9 set { numberA = value; } 10