簡體   English   中英

靜態工廠方法與公共構造函數

[英]Static factory method vs public constructor

背景:

這是我目前正在處理的代碼。 首先,基類是一個帳戶類,其中包含有關帳戶的信息並具有一些方法,這些方法在大多數情況下會更改類的屬性的值。

public class Account {
    private string _username; [...]

    public string Username { get { return _username; } } [...]

    public Account() { }

    public Account(string[] args) { [...] }

    public virtual void ChangePassword(string newPassword) { [...] }
}

然后,我有另一個用於創建帳戶的類,我將其命名為ActiveAccount。 這包含了我要用於帳戶的操作的大多數邏輯,這些邏輯只有在創建帳戶后才可能執行。 無需包括某些類來解釋該問題。 用您的想象力假設這些課程可以做什么:

public class ActiveAccount : Account
{
    private List<Conversation> _conversations; [...]

    public List<Conversation> Conversations { get { return _conversations; } } [...]

    private ActiveAccount() { }

    public static ActiveAccount CreateAccount(Account account)
    {
        // Navigate to URL, input fields, create account, etc.
    }

    public override void ChangePassword(string newPassword)
    {
        // Navigate to URL, input fields, change password, etc.

        // Update property using base method, if no errors.
        base.ChangePassword(newPassword);
    }
}

我使用靜態工廠方法有兩個原因。 1)我想要一個可自定義和可擴展的對象構造(例如,將來我可能有一個AccountTemplate,可以從中提供通用信息來創建帳戶;我可以使用AccountTemplate參數輕松創建另一個靜態工廠方法重載),以及2 )具有無參數的構造函數,這使我可以更輕松地將此對象序列化為XML / JSON。

題:

但是,引起我注意的是,我可以很容易地擁有一個接受Account參數,執行邏輯並可以重載進行擴展的公共構造函數。 我可以保留我的私有無參數構造函數,以防止無參數構造並允許序列化。

我是編程新手。 我想知道的是,是否有特定的原因使用靜態工廠方法而不是公共構造函數,如上所述。 做我想做的事的首選方式是什么?

我不會稱您使用的是靜態工廠。 在我看來,它是“命名構造函數”,因為它駐留在類本身中,並且僅創建該特定類的對象。

它通常用於使操作更易於理解,例如比較

int value = Int32.Parse(someString);
int value = new Int32(someString); // doesn't really exist

第一個版本清楚地說明了它解析輸入字符串,第二個版本則不那么冗長。

更新:構造函數和靜態方法(如Int32.Parse )之間的重要區別是,靜態方法可以選擇是否在發生錯誤時返回null或引發異常。 構造函數只能拋出一個異常,或者-我不建議這樣做-將對象置於某種狀態,在該狀態中它僅被半初始化。


靜態工廠用於解耦類,並使更改實現更容易,例如,每次需要數據庫連接時,都無需使用代碼中的new運算符實例化數據庫連接,而是使用返回接口的工廠方法:

SqlConnection myConnection = new SqlConnection(connectionString);
IDbConnection myConnection = myFactory.CreateConnection();

優點是,只需更改CreateConnection方法,即可對整個項目進行全局更改,交換數據庫服務器甚至數據庫提供程序,而不必在實際使用數據庫連接的所有位置上更改代碼。

我建議您閱讀.NET構造函數指南 在某些情況下,可能會導致選擇靜態工廠而不是構造函數。

在構造函數中完成最少的工作。 除了捕獲構造函數參數外,構造函數不應做太多工作。 任何其他處理的成本都應延遲到需要時再進行。

如果所需操作的語義沒有直接映射到新實例的構造,或者如果遵循構造函數設計准則感到不自然,請考慮使用靜態工廠方法而不是構造函數。

我需要考慮何時需要使用靜態工廠方法以及何時使用構造函數。

1)如果需要執行一些構造函數無法完成的其他動作/初始化,請使用靜態工廠方法。 例如,如果您需要發布新創建的ActiveAccount對象(例如SomePublicList.Add(ActiveAccount); ),那么從它自己的構造函數中發布它是一個壞習慣。

2)考慮繼承。 如果您需要為ActiveAccount創建一個后代類(例如NewActiveAccout ),則需要在ActiveAccount提供一個非私有的構造函數。 在這種情況下,也許您需要使用構造方法而不是工廠方法。

3)如果需要將一些參數傳遞給基類( Account )構造函數,則需要在ActiveAccount實現構造函數,因為您無法從靜態工廠方法將參數傳遞給基類構造函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM