开发者

When to use a Constructor and when to use getInstance() method (static factory methods)?

  1. When and how should we use a constructor

    Foo bar = new Foo();
    
  2. And when and how should we use getInstance() (static factory methods)

    Foo bar = Foo.getInstance(开发者_如何学JAVA);
    

What is the difference between these two? I have always used a constructor, but when should I use getInstance() instead?


Everybody seems to focus on singletons while I think that the question is actually about constructor vs static factory methods.

This is actually Item 1: Consider static factory methods instead of constructors of Effective Java by Joshua Bloch:

Item 1: Consider static factory methods instead of constructors

The normal way for a class to allow a client to obtain an instance of itself is to provide a public constructor. There is another technique that should be a part of every programmer’s toolkit. A class can provide a public static factory method, which is simply a static method that returns an instance of the class. Here’s a simple example from Boolean (the boxed primitive class for the primitive type boolean). This method translates a boolean primitive value into a Boolean object reference:

public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

Note that a static factory method is not the same as the Factory Method pattern from Design Patterns [Gamma95, p. 107]. The static factory method described in this item has no direct equivalent in Design Patterns.

A class can provide its clients with static factory methods instead of, or in addition to, constructors. Providing a static factory method instead of a public constructor has both advantages and disadvantages.

Advantages (quoting the book):

  • One advantage of static factory methods is that, unlike constructors, they have names.
  • A second advantage of static factory methods is that, unlike constructors, they are not required to create a new object each time they’re invoked.
  • A third advantage of static factory methods is that, unlike constructors, they can return an object of any subtype of their return type.
  • A fourth advantage of static factory methods is that they reduce the verbosity of creating parameterized type instances.

Disadvantages (still quoting the book):

  • The main disadvantage of providing only static factory methods is that classes without public or protected constructors cannot be subclassed.
  • A second disadvantage of static factory methods is that they are not readily distinguishable from other static methods.


You've got two questions: when should I call a getInstance() method, and when should I create one?

If you're deciding whether to call a getInstance() method, it's easy. You just need to read the class documentation to find out when you should call it. For example, NumberFormat provides a constructor and a getInstance() method; the getInstance() method will give you a localized NumberFormat. For Calendar, on the other hand, the constructor is protected. You have to call getInstance() to get one.

If you're deciding whether to create a getInstance() method, you need to decide what you're trying to accomplish. Either you don't want people to call your constructor (you're creating a singleton or a factory), or you don't mind (as in NumberFormat above, where they're initializing some objects for the convenience of the caller).


Long story short? Don't worry about creating getInstance() methods in your own code. If the time arises when they'll be useful, you'll know. And in general, if you can call a class's constructor, you're probably supposed to be doing that, even if the class provides a getInstance() method.


The uses for getInstance methods:

  • If you want to control/restrict construction e.g. Singleton
  • implement Factory pattern, e.g. DriverManager.getConnection
  • When you want to provide better name as to how the instance is constructed (constructors must have the same name as the class name), checkout the NumberFormat factory methods getCurrencyInstance, getIntegerInstance and others as examples of this.

But most of the time your object will be a simple POJO and usage of public constructors is most practical and obvious solution.

U1: getInstance From Another Class

To return an instance of a different class:

public class FooFactory {
    public static Foo getInstance() {
        return new Foo();
    }
}

NumberFormat.getInstance methods do this as they actually return instances of DecimalFormat.

U2: Singleton Problems

The singleton pattern restricts many of the benefits of object oriented programming. Singletons generally have private constructors, therefore you cannot extend them. As you will be accessing it via its getInstance method and not referencing any interface, you will not be able to swap it out for another implementation.


If you can use both then it sound like a poorly implemented singleton pattern.

Use the second option if you intend to have only one single instance of the class in your system and make the constructor private then.

Use the first to allow building several objects of the class.

BUT do not give your class the both possibilities.

Take care not to over-use singletons, only use them if really only one instance shall exist in the system otherwise you would limit the possibilities of re-use of your class in other projects. It sounds interesting to be able to call getInstance from everywhere in your project but that makes unclear who actually owns that instance: nobody and/or all. If you have a lot of singletons in a project you can bet that the system is poorly designed (usually). Singletons should be used with care, the same advice than for global variables apply.


One case in which I always prefer a static factory over a regular constructor is when I know the object construction will be slowish. I do simple initialization on constructor, but if I need to create something heavy I'll use a static method and document the behavior.


Singletons are evil. The problems I've seen surrounding it are not about re-use or extendability of a system (although I could see how that could occur), more so that I can't count the number of times i've seen obscure bugs in a system that arise from singletons.

If you do need to use a singleton, ensure it's scope is extremely narrow, i.e. judiciously limit the number of other objects in your system that know about it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜