昨天有稍微提到了一個反例:把方法共同的參數放在建構子傳入,在上禮拜的工廠方法的主題中,也提到了可以使用工廠方法來取代建構子,不知道有沒有人好奇那建構子要拿來做什麼呢?今天我們就來聊聊建構子應該做哪些事情。
我們繼續使用昨天的ReverseExpression的例子,可以發現我們把term移出之後,BinaryExpression也沒有必要隨著迴圈每次重建。而且比起放在方法裡面,他其實更適合放在建構子裡面,讓所有方法都可以使用。
public class ReverseExpression
{
public double Evaluate(string expression)
{
var terms = new Stack<double>();
foreach (var term in expression.Split(' '))
{
var binaryExpression = new BinaryExpression();
if (binaryExpression.IsValidOperator(term))
{
terms.Push(binaryExpression.Calculate(term, terms.Pop(), terms.Pop()));
}
else
{
terms.Push(double.Parse(term));
}
}
return terms.First();
}
}
是不是覺得又與昨天提到的有點矛盾了呢?
使用建構子初始化相依物件
public class ReverseExpression
{
private readonly BinaryExpression _binaryExpression;
public ReverseExpression(BinaryExpression binaryExpression)
{
_binaryExpression = binaryExpression;
}
...
}
初始化物件狀態
從Remote API收到Response時,我們會把它轉換成商業邏輯使用的Model
public class UserInfo
{
public int UserId {get; set;}
public int UserName {get; set;}
public string Avatar {get; set;}
...
public UserInfo(GetUserInfoResponse getUserInfoResponse)
{
UserInfo = userInfoResponse.UserId;
UserName = userInfoResponse.UserName;
Avatar = userInfoResponse.Avatar;
...
}
}
另一種是從兩個Model組出另外一個Model,通常使用這種這做法時,建構子裡頭會包含一些簡單的計算來初始化狀態。
public class Order
{
public int UserId {get; set;}
public int GoodsId {get; set;}
public decimal Price {get; set;}
public DateTime OrderDate {get; set;}
...
public Order(User user, Goods goods)
{
UserId = user.Id;
GoodsId = goods.Id;
Price = goods.price;
OrderDate = DateTime.Now;
...
}
}