Which one of the following way is recommended and why?
Date d = Date.from(curr);
Date d = new Date(curr);
Can you also provide some examples behind the reasoning?
Which one of the following way is recommended and why?
Date d = Date.from(curr);
Date d = new Date(curr);
Can you also provide some examples behind the reasoning?
Constructors are the expected way to well... construct a new object. If I'm creating a new object, the first thing I'll do is type in ClassName x = new ClassName(
and see what my IDE suggests to me as some options. As such, use constructors unless there's a good reason not to.
That said, constructors do have some disadvantages. For example, let's say my my Date
class had the ability to construct itself from either "seconds since 1970" or "milliseconds since 1970". In that case, I couldn't have constructors for both of those because they may well both use long
as their parameter. However, I could use static factories:
Date d = Date.fromUnixTimeSeconds(secondsSince1970);
Date d = Date.fromUnixTimeMilliseconds(secondsSince1970 * 1000);
There are some differences for the consuming client: a factory method could return a new object, or it could lookup and return an old one. Further, a factory method could return a subclass instead of the named class. (A factory method could also return null, though that would be counter intuitive and probably counter productive.)
Whereas in most languages, a constructor must return a new object of the exact type specified by the new
expression, with no possibility for (the above mentioned) alternatives that would be allowed a factory method.
(For example, a new
expression must construct new reference unequal to any other reference of any currently existing object; in C# and Java, for example, this includes immutable objects like strings, so new String ("x") != new String ("x")
where here I use != for reference inequality.)
However, we can't get away from constructors, someone somewhere has to use them to create objects or else we have no objects!
The question then is whether to make the constructor and factory or just constructor. If you offer a factory method, that provides a level of indirection (and a place for doing maintenance) that allows for certain flexibility. When offering a factory method, you can also make the constructors private (or protected) such that their usage is restricted, effectively forcing the consuming clients to use the factory method.
You're suggesting there's two alternatives, constructor vs. static factory method, though when it comes to factory methods, there are additional options if you really want to put flexibility into program architecture — one such option is an instance factory method: an instance method (of another class, a factory or context object). This makes the factory a first class entity like any other object. This approach offers yet one more level of decoupling and gives the consuming clients the most flexibility and control. For example, multiple instances (of such factory objects) can coexist in the program, and be used, passed as parameters, etc... and the program (e.g. the consuming clients) have the control to use (or provide) the right one in the right places.
From an outside point of view, constructors are just static methods that are invoked with unusual syntax.
However, constructors are not ordinary methods from a viewpoint within that class: the constructor must fully initialize an object, so treating constructors specially allows the language to provide special checks. E.g. in Java, the constructor must assign all final
fields. Because a constructor is focused on initialization, some people argue that a constructor should not be doing any meaningful work.
Furthermore, a constructor may play a special role in the language's semantics. E.g. C++ default constructors and copy constructors may be required by many standard library methods. C# interfaces can contain a constructor signature. A deserialization framework may discover constructors via reflection.
When designing a class, I tend to use the following approach to decide whether I should offer a public constructor or an ordinary static method (which would probably use a private constructor):
An advantage of a factory is you can reject invalid parameters without doing something like throwing an exception inside the constructor and/or or returning a partially built object. Theoretically someone could try and bypass your factory and call the constructor directly, but if you go with factories the use of the constructor directly should stick out in version control and/or bug hunting.
Also, if an unexpected error occurs in the constructor you can catch it (and maybe log it?) and just return nothing (this assumes you are more interested in keeping the program running than getting that particular object back).
You can do all these things without a factory, but a factory can centralize such code in a easy-to-find method.
However as noted by Erik, the factory method is only obligated to return something which matches the return type of the factory Create() method (as opposed to the constructor which must return that type), which could be a subclass of the class you want.
The Liskov Substitution Principle tells us that a subclass (what our factory might return) should be able to be used in the same place as the base class (what our constructor would return) without issue.
However in practice enforcing the LSP may be tricky. So the fact that the factory may return a subclass is still a potential issue. You could create a wrapper around all factory methods to check that the returned type is actually the class you expect, but then you must think of what to do when that issue occurs at runtime, rather than knowing at compile-time that your type will be what you expect.