简单工厂模式
1.1 面试受挫
#include <iostream>
using namespace std;
int main(void)
{
cout << "请输入数字" << endl;
int A = 0;
cin >> A;
cout << "请输入运算符号(+、-、*、/)" << endl;
char B = '+';
cin >> B;
cout << "请输入数字" << endl;
int C = 0;
cin >> C;
int D = 0;
if ( B == '+' )
D = A + C;
if ( B == '-' )
D = A - C;
if ( B == '*' )
D = A * C;
if ( B == '/' )
D = A / C;
cout << "结果是" << D << endl;
return 0;
}
1.2 初学者的毛病
(1) A,B,C,D的变量命名不规范
(2) 判断分支,意味着每个条件都要判断,计算机额外做了三次判断操作
(3) 没有判断除0的条件
(4) 没有考虑到用户输入出错的问题
1.3 规范代码
#include <iostream>
using namespace std;
// exception constant
#define DIVID_ZERO_ERROR 0
// function return constant
#define OK 0
#define ERROR -1
//from input stream read a integer
int ReadInt ( char *tipMessage = "Input Error,you must enter an integer,please again:")
{
int readResult = 0;
cin >> readResult;
while ( cin.fail() )
{
cout << tipMessage << endl; //show the user a tip message
cin.clear(); //reset the fail flag to zero
cin.sync(); //clear the data of the input stream
cin >> readResult;
}
return readResult;
}
int main(void)
{
try
{
cout << "Please enter an integer:" << endl;
int numberA = ReadInt ();
cout << "Please enter an operator(+、-、*、/)" << endl;
char arithOperator = '+';
cin >> arithOperator;
cout << "Please enter an integer:" << endl;
int numberB = ReadInt ();
int result = 0;
switch ( arithOperator )
{
case '+':
result = numberA + numberB;
break;
case '-':
result = numberA - numberB;
break;
case '*':
result = numberA * numberB;
break;
case '/':
if ( numberB == 0 )
{
throw (DIVID_ZERO_ERROR);
}
else
{
result = numberA / numberB;
}
break;
default:
break;
}
//out put the result
cout << "The result is " << result << endl;
}
catch ( int errorId)
{
switch (errorId)
{
case DIVID_ZERO_ERROR:
cout << "Dividing a zero is an error!" << endl;
break;
default:
cout << "unknown error id!";
}
return ERROR;
}
return OK;
}
1.4 面向对象编程
(1)可维护
(2)可复用
(3)可扩展
(4)灵活性好
1.6
通过封装、继承、多态把程序的耦合度降低,用设计模式使得程序更加的灵活,容易修改,并且易于复用。
1.7
小菜: 复制还是复用,这是个问题。
大鸟: 问题你个头,当然是复用啦!
1.8
业务逻辑应该与界面逻辑分开,让它们之间的耦合度降低。
分开才容易维护或者扩展。
#include <iostream>
using namespace std;
#define DIVIED_ZERO_ERROR 0
#define NO_DEFINED_OPERATOR 1
#define OK 0
#define ERROR -1
class ArithOperation
{
public:
static double GetResult (double numberA, double numberB, char arithOperator)
{
double result = 0;
switch ( arithOperator)
{
case '+':
result = numberA + numberB;
break;
case '-':
result = numberA - numberB;
break;
case '*':
result = numberA * numberB;
break;
case '/':
if (numberB == 0)
throw (DIVIED_ZERO_ERROR);
result = numberA / numberB;
break;
default:
throw ( NO_DEFINED_OPERATOR );
break;
}
return result;
}
};
double ReadDouble ( char * tipMessage = "Input Error!Please enter an double number again:")
{
double result = 0.0;
cin >> result;
while (cin.fail())
{
cout << tipMessage << endl;
cin.clear();
cin.sync();
cin >> result;
}
return result;
}
int main (void)
{
try
{
cout << "Please Enter an dobule number:" << endl;
double numberA = ReadDouble ();
cout << "Please Enter an arithmetic operator:" << endl;
char arithOperator;
cin >> arithOperator;
cout << "Please Enter an double number:" << endl;
double numberB = ReadDouble ();
double result = 0;
result = ArithOperation::GetResult ( numberA, numberB, arithOperator );
cout << "The result is" << result << endl;
}
catch ( int errorId )
{
switch (errorId)
{
case DIVIED_ZERO_ERROR:
cout << "Dividing zero is error." << endl;
break;
case NO_DEFINED_OPERATOR:
cout << "The opeartor is not defined." << endl;
break;
default:
cout << "unknow error!" << endl;
break;
}
return ERROR;
}
return OK;
}
1.9 紧耦合和松耦合
#include <iostream>
using namespace std;
#define DIVIED_ZERO_ERROR 0
#define OPERATION_TYPE_ERROR 1
#define OK 0
#define ERROR 1
class arithOperator
{
protected:
double numberA;
double numberB;
public:
arithOperator()
{
numberA = 0;
numberB = 0;
}
void SetNumberA (double number)
{
numberA = number;
}
double GetNumberA ()
{
return numberA;
}
void SetNumberB (double number)
{
numberB = number;
}
double GetNumberB ()
{
return numberB;
}
virtual double GetResult ()
{
double result = 0;
return result;
}
};
class OpeartionAdd : public arithOperator
{
virtual double GetResult ()
{
double result = 0;
result = numberA + numberB;
return result;
}
};
class OperationSub : public arithOperator
{
virtual double GetResult ()
{
double result = 0;
result = numberA - numberB;
return result;
}
};
class OperationMul : public arithOperator
{
virtual double GetResult ()
{
double result = 0;
result = numberA * numberB;
return result;
}
};
class OperationDiv : public arithOperator
{
virtual double GetResult ()
{
if (numberB == 0)
{
throw (DIVIED_ZERO_ERROR);
}
double result = 0;
result = numberA / numberB;
return result;
}
};
double ReadDouble ( char * tipMessage = "Input error!Please enter an double number again:\n")
{
double result = 0;
cin >> result;
while (cin.fail())
{
cout << tipMessage << endl;
cin.clear();
cin.sync();
cin >> result;
}
return result;
}
class OperationFactory
{
public:
static arithOperator* createOperator( char operType)
{
arithOperator *operPointer = NULL;
switch (operType)
{
case '+':
operPointer = new OpeartionAdd();
break;
case '-':
operPointer = new OperationSub();
break;
case '*':
operPointer = new OperationMul();
break;
case '/':
operPointer = new OperationDiv();
break;
default:
throw OPERATION_TYPE_ERROR;
break;
}
return operPointer;
}
};
int main (void)
{
try
{
cout << "Please enter an double number:" << endl;
double numberA;
numberA = ReadDouble();
cout << "Please enter an operator:" << endl;
char userOperator;
cin >> userOperator;
cout << "Please enter an double number:" << endl;
double numberB;
numberB = ReadDouble();
arithOperator *operPointer;
operPointer = OperationFactory::createOperator (userOperator);
operPointer->SetNumberA(numberA);
operPointer->SetNumberB(numberB);
double result = 0;
result = operPointer->GetResult();
cout << "The result is " << result << endl;
delete operPointer;
return OK;
}
catch ( int errorId )
{
switch (errorId)
{
case DIVIED_ZERO_ERROR:
cout << "Diving zero is an error!" << endl;
break;
case OPERATION_TYPE_ERROR:
cout << "Operator type is error!" << endl;
break;
default:
cout << "Unknown error!" << endl;
break;
}
return ERROR;
}
}
总结:工厂只负责生产由用户指定的产品,这样的设计好处是每种产品独立,如果程序需要修改其中某一个产品,那么他不需要改动其它产品的代码,也不需要改动工厂的代码,当然,界面代码也不需要改动,改动的只是产品的内在。
如果要添加一种新的产品,则需添加新的类并修改工厂类。
注意:产品必须是同一种功能,也就是同样的方法名称。
C++步骤:
1.定义抽象类,并定义一个虚拟的方法
2.从该抽象类派生出子类,实现同一个方法
3.定义工厂,提供函数,根据用户的输入,生产出不同的对象,注意,这里用的是NEW,所以用
4.利用这个对象进行操作
5.删除对象
1.1 面试受挫
#include <iostream>
using namespace std;
int main(void)
{
cout << "请输入数字" << endl;
int A = 0;
cin >> A;
cout << "请输入运算符号(+、-、*、/)" << endl;
char B = '+';
cin >> B;
cout << "请输入数字" << endl;
int C = 0;
cin >> C;
int D = 0;
if ( B == '+' )
D = A + C;
if ( B == '-' )
D = A - C;
if ( B == '*' )
D = A * C;
if ( B == '/' )
D = A / C;
cout << "结果是" << D << endl;
return 0;
}
1.2 初学者的毛病
(1) A,B,C,D的变量命名不规范
(2) 判断分支,意味着每个条件都要判断,计算机额外做了三次判断操作
(3) 没有判断除0的条件
(4) 没有考虑到用户输入出错的问题
1.3 规范代码
#include <iostream>
using namespace std;
// exception constant
#define DIVID_ZERO_ERROR 0
// function return constant
#define OK 0
#define ERROR -1
//from input stream read a integer
int ReadInt ( char *tipMessage = "Input Error,you must enter an integer,please again:")
{
int readResult = 0;
cin >> readResult;
while ( cin.fail() )
{
cout << tipMessage << endl; //show the user a tip message
cin.clear(); //reset the fail flag to zero
cin.sync(); //clear the data of the input stream
cin >> readResult;
}
return readResult;
}
int main(void)
{
try
{
cout << "Please enter an integer:" << endl;
int numberA = ReadInt ();
cout << "Please enter an operator(+、-、*、/)" << endl;
char arithOperator = '+';
cin >> arithOperator;
cout << "Please enter an integer:" << endl;
int numberB = ReadInt ();
int result = 0;
switch ( arithOperator )
{
case '+':
result = numberA + numberB;
break;
case '-':
result = numberA - numberB;
break;
case '*':
result = numberA * numberB;
break;
case '/':
if ( numberB == 0 )
{
throw (DIVID_ZERO_ERROR);
}
else
{
result = numberA / numberB;
}
break;
default:
break;
}
//out put the result
cout << "The result is " << result << endl;
}
catch ( int errorId)
{
switch (errorId)
{
case DIVID_ZERO_ERROR:
cout << "Dividing a zero is an error!" << endl;
break;
default:
cout << "unknown error id!";
}
return ERROR;
}
return OK;
}
1.4 面向对象编程
(1)可维护
(2)可复用
(3)可扩展
(4)灵活性好
1.6
通过封装、继承、多态把程序的耦合度降低,用设计模式使得程序更加的灵活,容易修改,并且易于复用。
1.7
小菜: 复制还是复用,这是个问题。
大鸟: 问题你个头,当然是复用啦!
1.8
业务逻辑应该与界面逻辑分开,让它们之间的耦合度降低。
分开才容易维护或者扩展。
#include <iostream>
using namespace std;
#define DIVIED_ZERO_ERROR 0
#define NO_DEFINED_OPERATOR 1
#define OK 0
#define ERROR -1
class ArithOperation
{
public:
static double GetResult (double numberA, double numberB, char arithOperator)
{
double result = 0;
switch ( arithOperator)
{
case '+':
result = numberA + numberB;
break;
case '-':
result = numberA - numberB;
break;
case '*':
result = numberA * numberB;
break;
case '/':
if (numberB == 0)
throw (DIVIED_ZERO_ERROR);
result = numberA / numberB;
break;
default:
throw ( NO_DEFINED_OPERATOR );
break;
}
return result;
}
};
double ReadDouble ( char * tipMessage = "Input Error!Please enter an double number again:")
{
double result = 0.0;
cin >> result;
while (cin.fail())
{
cout << tipMessage << endl;
cin.clear();
cin.sync();
cin >> result;
}
return result;
}
int main (void)
{
try
{
cout << "Please Enter an dobule number:" << endl;
double numberA = ReadDouble ();
cout << "Please Enter an arithmetic operator:" << endl;
char arithOperator;
cin >> arithOperator;
cout << "Please Enter an double number:" << endl;
double numberB = ReadDouble ();
double result = 0;
result = ArithOperation::GetResult ( numberA, numberB, arithOperator );
cout << "The result is" << result << endl;
}
catch ( int errorId )
{
switch (errorId)
{
case DIVIED_ZERO_ERROR:
cout << "Dividing zero is error." << endl;
break;
case NO_DEFINED_OPERATOR:
cout << "The opeartor is not defined." << endl;
break;
default:
cout << "unknow error!" << endl;
break;
}
return ERROR;
}
return OK;
}
1.9 紧耦合和松耦合
#include <iostream>
using namespace std;
#define DIVIED_ZERO_ERROR 0
#define OPERATION_TYPE_ERROR 1
#define OK 0
#define ERROR 1
class arithOperator
{
protected:
double numberA;
double numberB;
public:
arithOperator()
{
numberA = 0;
numberB = 0;
}
void SetNumberA (double number)
{
numberA = number;
}
double GetNumberA ()
{
return numberA;
}
void SetNumberB (double number)
{
numberB = number;
}
double GetNumberB ()
{
return numberB;
}
virtual double GetResult ()
{
double result = 0;
return result;
}
};
class OpeartionAdd : public arithOperator
{
virtual double GetResult ()
{
double result = 0;
result = numberA + numberB;
return result;
}
};
class OperationSub : public arithOperator
{
virtual double GetResult ()
{
double result = 0;
result = numberA - numberB;
return result;
}
};
class OperationMul : public arithOperator
{
virtual double GetResult ()
{
double result = 0;
result = numberA * numberB;
return result;
}
};
class OperationDiv : public arithOperator
{
virtual double GetResult ()
{
if (numberB == 0)
{
throw (DIVIED_ZERO_ERROR);
}
double result = 0;
result = numberA / numberB;
return result;
}
};
double ReadDouble ( char * tipMessage = "Input error!Please enter an double number again:\n")
{
double result = 0;
cin >> result;
while (cin.fail())
{
cout << tipMessage << endl;
cin.clear();
cin.sync();
cin >> result;
}
return result;
}
class OperationFactory
{
public:
static arithOperator* createOperator( char operType)
{
arithOperator *operPointer = NULL;
switch (operType)
{
case '+':
operPointer = new OpeartionAdd();
break;
case '-':
operPointer = new OperationSub();
break;
case '*':
operPointer = new OperationMul();
break;
case '/':
operPointer = new OperationDiv();
break;
default:
throw OPERATION_TYPE_ERROR;
break;
}
return operPointer;
}
};
int main (void)
{
try
{
cout << "Please enter an double number:" << endl;
double numberA;
numberA = ReadDouble();
cout << "Please enter an operator:" << endl;
char userOperator;
cin >> userOperator;
cout << "Please enter an double number:" << endl;
double numberB;
numberB = ReadDouble();
arithOperator *operPointer;
operPointer = OperationFactory::createOperator (userOperator);
operPointer->SetNumberA(numberA);
operPointer->SetNumberB(numberB);
double result = 0;
result = operPointer->GetResult();
cout << "The result is " << result << endl;
delete operPointer;
return OK;
}
catch ( int errorId )
{
switch (errorId)
{
case DIVIED_ZERO_ERROR:
cout << "Diving zero is an error!" << endl;
break;
case OPERATION_TYPE_ERROR:
cout << "Operator type is error!" << endl;
break;
default:
cout << "Unknown error!" << endl;
break;
}
return ERROR;
}
}
总结:工厂只负责生产由用户指定的产品,这样的设计好处是每种产品独立,如果程序需要修改其中某一个产品,那么他不需要改动其它产品的代码,也不需要改动工厂的代码,当然,界面代码也不需要改动,改动的只是产品的内在。
如果要添加一种新的产品,则需添加新的类并修改工厂类。
注意:产品必须是同一种功能,也就是同样的方法名称。
C++步骤:
1.定义抽象类,并定义一个虚拟的方法
2.从该抽象类派生出子类,实现同一个方法
3.定义工厂,提供函数,根据用户的输入,生产出不同的对象,注意,这里用的是NEW,所以用
4.利用这个对象进行操作
5.删除对象