11

背景:

这是我目前正在处理的代码。首先是基类,它是一个帐户类,它保存有关帐户的信息,并具有一些在大多数情况下更改类属性值的方法。

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 参数的公共构造函数,执行逻辑并且可以很容易地通过重载进行扩展。我可以保留我的私有无参数构造函数以防止无参数构造并允许序列化。

我对编程很陌生。我想知道是否有特定原因使用静态工厂方法而不是公共构造函数,如上所述。做我想做的事情的首选方式是什么?

4

3 回答 3

22

我不会称您使用的是静态工厂。在我看来,它是一个“命名构造函数”,因为它驻留在类本身中并且只是创建该特定类的一个对象。

它通常用于使操作更易于理解,例如比较

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方法,您可以对整个项目进行全局更改,交换数据库服务器甚至数据库提供程序,而无需在您实际使用数据库连接的所有地方更改您的代码。

于 2014-03-06T11:47:04.360 回答
16

我建议您阅读.NET 构造函数指南。在您的情况下,有些要点可能会导致选择静态工厂而不是构造函数。即

在构造函数中做最少的工作。除了捕获构造函数参数之外,构造函数不应该做太多工作。任何其他处理的成本应延迟到需要时。

如果所需操作的语义不直接映射到新实例的构造,或者如果遵循构造函数设计指南感觉不自然,请考虑使用静态工厂方法而不是构造函数。

于 2014-03-06T11:47:18.080 回答
0

关于何时需要更喜欢静态工厂方法以及何时需要构造函数,我有一些考虑。

1) 如果您需要执行一些构造函数无法完成的额外操作/初始化,请使用静态工厂方法。例如,如果您需要发布新创建的ActiveAccount对象(例如SomePublicList.Add(ActiveAccount);),那么从它自己的构造函数中发布它是一种不好的做法。

2)考虑继承。如果您需要为其创建一个后代类(例如NewActiveAccout),ActiveAccount那么您需要在 中提供一个非私有构造函数ActiveAccount。在这种情况下,也许您需要更喜欢构造函数而不是工厂方法。

3) 如果你需要将一些参数传递给基类( Account) 构造函数,那么你需要实现一个构造函数,ActiveAccount因为你不能从静态工厂方法传递参数给基类构造函数。

于 2014-03-06T12:10:26.520 回答