Instantiating the object of the class isn’t really the most difficult job in the world. Rather I’d say its one of the most basic things about any programming language. As you must’ve guessed it, I’m referring to a constructor. A constructor is a method whose name is the same as that of the class its part of, and which returns the instance of the class. Like any other method, we could override a constructor. But is constructor the best way to deal with object instantiation? Let’s find out!
Why avoid using constructor?
Now even though its the simplest way to create an instance of an object, sometimes its better to avoid using plain old constructors. There can be multiple reasons for that:
1. Constructors do not have names. This has two disadvantages. You may want a better name for a method that returns an instance of a class rather than using the class name itself. Hence it would make the code cleaner and more readable. Another problem is because they do not give the freedom of choosing their name, overriding them becomes difficult. For example, you can not have more than one constructor having two string argument. It would give you a compile-time error. For example :
2. You create an instance each time you invoke a constructor. Ironic right? That’s what the job is, so what’s the problem? But there is! Sometimes we would like to control the number of instances that our class has or even the properties that are set for them! For such a use case, giving unfettered access to constructors may not be the way to go.
3. You can not change the return type. A constructor would return the instance of a class and that class only. There is no way we can change that. And more often than not, this is important for us to control.
Static factory over constructor
So above we discussed a few problems with using constructors. This blog is not just about the problem, it’s about the solution too. And one of the way to counter these or add more features to our arsenal is by using static factory methods. Static methods are methods that belong to the class, not to any particular instance. The “factory” here isn’t in reference to the factory pattern. The idea is to create public static methods that provide an instance of the class, in a controlled manner.
There could be a few advantages or improvements over plain old constructors.
1. Methods can have names. One can easily name them to be something more meaningful than the class name. For example, you could have a use-case where an employee object will have a department property. Considering it to be a software firm, more often the employee may be from the engineering department. So you could have a method like createEngineer( ) instead of a less meaningful constructor. Additionally, it’s more convenient to create multiple static factory methods as compared to overriding the constructor. In cases where the constructors have the same type and number of arguments, we often avoid the compile-time error by changing the order of the parameters. That’s not really the right way of doing things. One, because it could create confusion about which method we’re referring to and two because it would require additional documentation just to describe the use-case of both the methods. Enter static factory methods, where you can simply name them differently.
2. Methods don’t always need to create an instance. There are times when we would like to limit the instances of our class to a few predefined instances. For example Boolean.valueOf ( Boolean ). So we won’t really need to create an object, we could just return the same object once created repeatedly.
3. Methods can return a subtype of the return type. This can be a very useful tool for making things decoupled. Unlike constructors, a static factory method isn’t compelled to return something, it may return a subtype of the return type. An example of this is the interface based frameworks. In interface-based frameworks, the API developer only needs to provide an interface in return type which specifies the contract about what a client of that API can expect. When the client uses an API like that, all it cares is that the object being returned follows the contract provided by the interface. So in case the API provider comes up with an upgrade and provides a different implementation, it doesn’t have much impact on the client’s codebase. This makes things more decoupled in nature.
Additionally, this makes the API compact as the provider doesn’t have to reveal the implementation class to the client. It just needs to ensure that the returned type implements the contract.
Now while we have listed the advantages of using a static factory method, nothing comes without their share of limitations and static factory methods aren’t an exception to that.
- If you don’t expose a constructor, you may not be able to extend the class. Unless there is a public or a protected constructor, you may never be able to extend that particular class. This could be a useful way to avoid unwanted extension but could also be a restriction.
- Constructors stand out, static factory methods don’t. Constructors can be easily identified and generally, you wouldn’t require any additional information with it. However, you may need to provide additional documentation in order to use static factory methods.