天天看點

讀《大話設計模式》——①代碼無錯就是優?[簡單工廠模式]

題目: 請用C++、Java、C#或VB.NET任意一種面向對象語言實作一個電腦控制程式,要求輸入兩個數和運算符号,得到結果。

答案:

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 (B == "/")
		{
			D = Convert.ToString(Convert.ToDouble(A) / Convert.ToDouble(C));
		}

		Console.WriteLine("結果是:" + D);
	}
}

           

存在問題

  1. A、B、C、D的命名不規範
  2. 分支判斷,這樣寫,意味着每個條件都要做判斷,等于計算機做了三次無用功
  3. 除數為0怎麼辦?使用者輸入不是數字怎麼辦

答案2

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);
		}
	}
}

           

**存在問題:**程式不易維護、不易擴充、不易複用

答案3: 封裝業務邏輯,達到可維護或擴充

業務邏輯

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;
	}
}
           

用戶端

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 = "";
			strResult = Convert.ToString(Operation.GetResult(Convert.ToDouble(strNumberA), Convert.ToDouble(strNumberB), strOperate));
			Console.WriteLine("結果是:" + strResult);
			Console.ReadLine();
		}
		catch (Exception ex)
		{
			Console.WriteLine("您的輸入有錯:" + ex.Message);
		}
	}
}
           

**存在問題:**程式可複用,但不易維護、不易擴充,例如想要增加開根運算怎麼辦呢?答案3的方法需要提供源碼,重新編譯,顯然不符合題目要求。

答案4:繼承、多态、簡單工廠

/// <summary>
/// 運算類
/// </summary>
public class OperationBase
{
	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;
	}
}

/// <summary>
/// 加法類,繼承運算類
/// </summary>
public class OperationAdd : OperationBase//繼承
{
	public override double GetResult()
	{
		double result = 0;
		result = NumberA + NumberB;
		return result;
	}
}

/// <summary>
/// 減法類,繼承運算類
/// </summary>
public class OperationSub : OperationBase
{
	public override double GetResult()
	{
		double result = 0;
		result = NumberA - NumberB;
		return result;
	}
}

/// <summary>
/// 乘法類,繼承運算類
/// </summary>
public class OperationMul : OperationBase
{
	public override double GetResult()
	{
		double result = 0;
		result = NumberA * NumberB;
		return result;
	}
}

/// <summary>
/// 除法類,繼承運算類
/// </summary>
public class OperationDiv : OperationBase
{
	public override double GetResult()
	{
		double result = 0;
		if (NumberB == 0)
			throw new Exception("除數不能為0");
		result = NumberA / NumberB;
		return result;
	}
}

/// <summary>
/// 簡單運算工廠類
/// </summary>
public class OperationFactory
{
	public static OperationBase createOperate(string operate)
	{
		OperationBase oper = null;
		switch (operate)//多态
		{
			case "+":
				oper = new OperationAdd();
				break;
			case "-":
				oper = new OperationSub();
				break;
			case "*":
				oper = new OperationMul();
				break;
			case "/":
				oper = new OperationDiv();
				break;
			default:
				break;
		}
		return oper;
	}
}
           

用戶端

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();

			OperationBase oper = OperationFactory.createOperate(strOperate);
			oper.NumberA = Convert.ToDouble(strNumberA);
			oper.NumberB = Convert.ToDouble(strNumberB);
			double result = oper.GetResult();
			Console.WriteLine("結果是:" + result);
			Console.ReadLine();
		}
		catch (Exception ex)
		{
			Console.WriteLine("您的輸入有錯:" + ex.Message);
		}
	}
}

           

總結:

  1. 需要更改加法運算時,隻改加法類即可
  2. 需要增加其他算法,隻要增加相應的運算子類,還需要修改運算工廠類,在switch中增加分支

下載下傳源碼