设计模式 一 简单工场模式
来源:互联网 发布:零基础美工基础知识 编辑:程序博客网 时间:2024/06/05 14:43
前几天遇到一个面试题,问设计模式相关的东西。
完全没有答出来,所以痛定思痛,觉得好好研究一下什么是设计模式,就百度一一下,发现大话设计模式这本书。
确实写得不错,很生动形象,但是里面用的是c#,我本是不是特别懂c#就先用c++把它实现了。
本文主要围绕如何设计一个计算器为题目,来展开。
开始看到简单计算器的时候,觉得没有什么难度,但是自己仔细想了想,又实验了一下,发现其中还是大有文章。
里面有什么文章呢?这里计算器的操作数就两种类型int 和double
1 操作数的输入大小
你可以用电脑自带的计算器看一下,输入最大是16个有效数字。正数的输入范围是
0.0000000000000001--------9999999999999999
这个在设计输入的时候,要考虑清楚。
2 如果操作符左右两边是同一种类型,int, double。
那么如果操作符是+,-,*,我想当然的认为对于int两个数的结果也肯定是 int。
但是事实并非如此,听我慢慢道来,因为有个情况叫做越界。
我们可以用自带的计算机算一下,越界的时候并没有出问题。
9999999999999999 + 9999999999999999 =2.e+16
这是什么原因呢?很简单,计算器无论是int ,还是double,都先换算成double.
然后通过doulbe和int的类型去比较,如果两个差小于等于1e-15,那么就会按int显示出来。
3 int 和double运算
也是按上面的来做,原因很简单。
例如0.2*5 =1,而不能显示为1.0
还有个1+0.0000000000000001 显示的结果为1,而不是1.0000000000000001,大家可以计算一下试试,这个我开始想还以为是长度不够了,但是仔细看一下,发现是double的精度问题,有效数字0.0000000000000001是1个,而1.0000000000000001有效数字是17个,double自己会舍弃掉。
可见如果真的用计算机做精度极高的运算,要特别小心,重新设计计算符号。
所以,开始的时候我想用模板类来实现四则运算,是不对的。
但是如果做程序员的计算器则是合理的。
我们怎么设计这个呢?
简单工场的模式
将数据和运算分开。
1 先写运算操作类。
class Operation{public:Operation(double op1, double op2, char op);double getResult();private:double op1;double op2;char op;};
Operation::Operation(double op1, double op2, char op){this->op = op;this->op1 = op1;this->op2 = op2;}double Operation::getResult(){double result;switch(op){case '+':result = op1 + op2;break;case '-':result = op1 - op2;break;case '*':result = op1 * op2;break;case '/':if (op2< 1e-15 && op2>-1e-15){//异常处理return 0;}result = op1/op2;break;}return result;}
2 界面的设计
一个很简单的界面。
3 函数的成员变量
CString m_result; //最终的结果CString m_op1; //第一个操作数CString m_op2; //第二个操作数CString m_current;//当前屏幕显示的char m_operator; // 操作符int m_opStat;//0 表示当前对第一个数进行输入,1表示当前对第二个数进行输入bool m_inputStat;// 输入状态,如果出现异常,包括除以0,超过最大的数等,禁止任何操作bool m_isInt;//输入是否为整数,主要用于区分.int m_dataLength;//输入长度,不能超过1e17
4 结果重要的函数
输入函数:主要输入条件,小于最大长度,输入状态为true
void Cdesign_1_calculateDlg::refreshText(int input){if(m_inputStat && m_dataLength <= MAX_LENGTH){CString str;str.Format(_T("%d"),input);m_current += str;CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT1);pEdit->SetWindowText(m_current);if (m_opStat==0){m_op1 = m_current;}else{m_op2 = m_current;}m_dataLength++;}}
点击操作符,需要切换操作数,输入长度和当前显示都要清空。点操作符状态清空
void Cdesign_1_calculateDlg::setOperator(char input){m_operator = input;m_opStat = 1;m_current.Empty();m_dataLength = 0;
m_isInt = true;}
输入.字符
只需要注意一点,就是只能进入一次。这里命名比较乱,用的都是数字。
void Cdesign_1_calculateDlg::OnBnClickedButton5(){// TODO: 在此添加控件通知处理程序代码if(m_isInt){ m_isInt = false;CString str;str.Format(_T("%c"),'.');m_current += str;CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT1);pEdit->SetWindowText(m_current);}}
最后显示函数,命名不好
void Cdesign_1_calculateDlg::OnBnClickedButton15(){// TODO: 在此添加控件通知处理程序代码if (1 == m_opStat && true == m_inputStat){double input1 = (double)_wtof(m_op1);double input2 = (double)_wtof(m_op2);if('/' == m_operator && (input2) < 1e-15 && (input2)> -1e15){CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT1);pEdit->SetWindowText(_T("除数不能为0"));m_inputStat = false;return;}Operation operation(input1,input2,m_operator);double result = operation.getResult();long long int intResult = static_cast<long long int>(result);double dif = result - intResult;if(dif <1e-15 && intResult < 1e16)m_result.Format(_T("%ld"),intResult);elsem_result.Format(_T("%g"),result);CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT1);pEdit->SetWindowText(m_result);m_op1 = m_result;m_current = m_result;}}
显示的时候要区分int 型的和double类型的。
5 一些问题
- 设计模式 一 简单工场模式
- 设计模式---简单工场模式
- 设计模式-简单工场模式
- android设计模式--简单工场模式
- 设计模式-工场模式
- Java设计模式(一)普通工场模式 抽象工场模式
- 设计模式---工场方法模式
- 设计模式---抽象工场模式
- IOS设计模式之工场模式
- C# 设计模式-工场方法模式
- 创建型模式之简单工场模式
- 设计模式——《大话设计模式》——简单工厂模式+策略模式+策略与简单工场结合
- 工场模式
- 工场模式
- 【设计模式】工场模式 || 抽象工厂 || 观察者模式 || 代理模式
- 简单工场、工场方法、抽象工厂模式浅析
- 设计模式一 简单工厂设计模式
- 工场设计模式和抽象工厂设计模式
- 第1章 Android开发简介
- Ubuntu10.04升级2.6.38内核
- Android关于ExpandableListView用法的一个简单小例子。仿QQ列表
- Oracle Dataguard 的配置安装
- 第3章 Android程序设计基础
- 设计模式 一 简单工场模式
- ubuntu 下安装memcache
- 一道残忍的数学题
- android json解析及简单例子
- Qt实现客户端/服务器端登录验证|数据传输使用md5加密
- 第4章 用户界面开发基础
- 谈谈本次acm之行
- 在STS中写一个Servlet项目
- android有用代码片段