Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static factory method vs public constructor

Background:

Here's the code for what I'm currently working on. First, the base class, which is an account class that holds information about the account and has some methods that for the most part change the values of the class's properties.

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

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

    public Account() { }

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

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

Then, I have another class for when the account has been created, which I have named ActiveAccount. This contains most of the logic for the actions I want to use for the account that are only possible once the account has been created. Some classes need not to be included to explain the question; use your imagination to assume what those classes may do:

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

I've used a static factory method for two reasons. 1) I want customiseable and extensible construction of an object (for example, in the future I might have an AccountTemplate from which I provide generic information to create accounts; I can easily create another static factory method overload with an AccountTemplate parameter), and 2) having a parameterless constructor allows me to serialize this object more easily into XML/JSON.

Question:

However, it's come to my attention that I could just as easily have a public constructor that accepts an Account parameter, performs the logic and can be extended with overloads just as easily. I can keep my private parameterless constructor to prevent parameterless construction and allow serialization.

I'm quite new to programming. What I'm wondering is if there is a specific reason to use static factory methods instead of public constructors, as explained above. And what's the preferred way of doing what I want to do?

like image 552
Nick Bull Avatar asked Mar 06 '14 11:03

Nick Bull


People also ask

What is the benefit to use static factory in place of constructor?

Static factory methods can encapsulate all the logic required for pre-constructing fully initialized instances, so they can be used for moving this additional logic out of constructors. This prevents constructors from performing further tasks, others than just initializing fields.

Why would one use the factory method rather than just using a constructor?

The factory method is a smart way to create objects in Java and provides several advantages over the traditional approach of creating objects using constructors in Java. It can also improve the quality of code by making the code more readable, less coupled, and improves performance by caching.

When would you use a static factory method?

A static factory method is a public static method on the object that returns a new instance of the object. These type of methods share the same benefits as the traditional factory method design pattern. This is especially useful for value objects that don't have a separate interface and implementation class.

Should a factory method be static?

Specifically with the Factory pattern, no, there is no requirement that the factory methods be static. The essence of the pattern is that you have one object which is responsible for creating instances of another class.


2 Answers

I would advise you to read the .NET constructor guidelines. There are some points that probably leads to choosing a static factory instead of a constructor in your case. Namely

Do minimal work in the constructor. Constructors should not do much work other than to capture the constructor parameters. The cost of any other processing should be delayed until required.

and

Consider using a static factory method instead of a constructor if the semantics of the desired operation do not map directly to the construction of a new instance, or if following the constructor design guidelines feels unnatural.

like image 85
Ondrej Janacek Avatar answered Oct 06 '22 06:10

Ondrej Janacek


I wouldn't call what you used a static factory. In my eyes it's a "named constructor" since it resides in the class itself and just creates an object of that particular class.

It is often used to make the operation easier to understand, e.g. compare

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

The first version makes it clear that it parses the input string, the second is far less verbose.

Update: one important difference between constructors and static methods like Int32.Parse is that static methods can chose whether to return null in case an error occured or throw an exception. A constructor can only throw an exception or - and I wouldn't recommend that - leave the object in some sort of limbo state where it is only half-initialized.


A static factory is used to decouple classes, and to make it easier to change the implementation, for example instead of instantiating a database connection using the new operator in your code every time you need a database connection you use a factory method that returns an interface:

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

The advantage is that by simply changing the CreateConnection method you can make global changes to your entire project, swapping databases servers or even database providers without having to change your code in all the places where you actually use the database connection.

like image 23
Dirk Avatar answered Oct 06 '22 06:10

Dirk