本文内容参考自《大话设计模式》(程杰 著)
注:以下代码为C#实现
class Program
{
static void Main(string[] args)
{
Console.Write("请输入数字A:");
string A = Console.ReadLine();
Console.Write("请选择运算符号(+、-、*、/):");
string B = Console.ReadLine();
Console.Write("请输入数字B:");
string C = Console.ReadLine();
string D = "";
if (B == "+")
D = Convert.ToString(Convert.ToDouble(A) + Convert.ToDouble(C));
if (B == "-")
D = Convert.ToString(Convert.ToDouble(A) - Convert.ToDouble(C));
if (B == "*")
D = Convert.ToString(Convert.ToDouble(A) * Convert.ToDouble(C));
if (O == "/")
D = Convert.ToString(Convert.ToDouble(A) / Convert.ToDouble(C));
Console.WriteLine("结果是:" + D);
}
}
毛病:命名不规范,判断分支做多次无用功,除数为0时出错,输入不是数字……
class Program
{
static void Main(string[] args)
{
try
{
Console.Write("请输入数字A:");
string strNumberA = Console.ReadLine();
Console.Write("请选择运算符号(+、-、*、/):");
string strOperate = Console.ReadLine();
Console.Write("请输入数字B:");
string strNumberB = Console.ReadLine();
string strResult = "";
switch (strOperate)
{
case "+":
strResult = Convert.ToString(Convert.ToDouble(strNumberA)
+ Convert.ToDouble(strNumberB));
break;
case "-":
strResult = Convert.ToString(Convert.ToDouble(strNumberA)
- Convert.ToDouble(strNumberB));
break;
case "*":
strResult = Convert.ToString(Convert.ToDouble(strNumberA)
* Convert.ToDouble(strNumberB));
break;
case "/":
if (strNumberB != "0")
strResult = Convert.ToString(Convert.ToDouble(strNumberA)
/ Convert.ToDouble(strNumberB));
else
strResult = "除数不能为0";
break;
}
Console.WriteLine("结果是:" + strResult);
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("您的输入有错:" + ex.Message);
}
}
}
以上代码规范了,但是可重用性差!
Operation运算类
public class Operation
{
public static double GetResult(double numberA, double numberB, string operate)
{
double result = 0d;
switch (operate)
{
case "+":
result = numberA + numberB;
break;
case "-":
result = numberA - numberB;
break;
case "*":
result = numberA * numberB;
break;
case "/":
result = numberA / numberB;
break;
}
return result;
}
}
客户端代码
static void Main(string[] args)
{
try
{
Console.Write("请输入数字A:");
string strNumberA = Console.ReadLine();
Console.Write("请选择运算符号(+、-、*、/):");
string strOperate = Console.ReadLine();
Console.Write("请输入数字B:");
string strNumberB = Console.ReadLine();
string strResult = "";
strResult = Convert.ToString(Operation.GetResult(Convert.ToDouble(strNumberA),
Convert.ToDouble(strNumberB), strOperate));
Console.WriteLine("结果是:" + strResult);
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("您的输入有错:" + ex.Message);
}
}
问题:如果我要增加其他运算,或者是想要修改运算的法则,那么其他代码都会受到影响,比如要重新编译,调试等等。
Operation运算类
public class Operation
{
private double _numberA = 0;
private double _numberB = 0;
public double NumberA
{
get { return _numberA; }
set { _numberA = value; }
}
public double NumberB
{
get { return _numberB; }
set { _numberB = value; }
}
public virtual double GetResult()
{
double result = 0;
return result;
}
}
加减乘除类
class OperationAdd : Operation
{
public override double GetResult()
{
double result = 0;
result = NumberA + NumberB;
return result;
}
}
class OperationSub : Operation
{
public override double GetResult()
{
double result = 0;
result = NumberA - NumberB;
return result;
}
}
class OperationMul : Operation
{
public override double GetResult()
{
double result = 0;
result = NumberA * NumberB;
return result;
}
}
class OperationDiv : Operation
{
public override double GetResult()
{
double result = 0;
if (NumberB==0)
throw new Exception("除数不能为0。");
result = NumberA / NumberB;
return result;
}
}
在这里,我们定义了一个虚函数,然后其他运算继承操作类并实现该函数,这样子,如果要增加其他运算,只需要增加一个类来继承操作类就可以了,而且单个操作的修改完全不影响其他的运算!
使用上面代码之后,我们在客户端需要实例化相应的类,比如‘+’操作需要实例化OperationAdd,减操作需要实例化OperationSub,这样子暴露给客户的信息太多了,客户必须知道每个操作它对应的类!
使用简单的工厂模式可以避免这个问题:
简单运算工厂类
public class OperationFactory
{
public static Operation createOperate(string operate)
{
Operation oper = null;
switch (operate)
{
case "+":
oper = new OperationAdd();
break;
case "-":
oper = new OperationSub();
break;
case "*":
oper = new OperationMul();
break;
case "/":
oper = new OperationDiv();
break;
}
return oper;
}
}
客户端代码
Operation oper;
oper = OperationFactory.createOperate(“+”);
oper.NumberA = 1;
oper.NumberB = 2;
double result = oper.GetResult();
如果一来,客户端就简化了很多,它只需要知道 OperationFactory,并通过createOperate传入相应的操作就可以了!
当我们需要修改加法运算时,只需要修改OperationAdd,当我们需要增加其他运算时,只需要增加相应的运算子类,并在运算类工厂中增加分支即可。
同时,界面显示和我们的业务逻辑也是分离的~