10

Having worked with C# before, I have considered

Calendar cal = Calendar.getInstance();

to be a singleton method according the GoF Singleton pattern (Wikipedia) and I wondered how to create two calendars, since Dateis somewhat deprecated.

From the documentation

Gets a calendar using the default time zone and locale.

and the overloads

getInstance(TimeZone zone)
getInstance(Locale aLocale)

this seemed to me to be a generalization of the singleton pattern to create a singleton per time zone and locale. But I wanted two calendars in the same time zone.

However, when I conducted the test

@Test
public void test()
{
    Calendar cal = Calendar.getInstance();
    Calendar cal2 = Calendar.getInstance();
    assertTrue(cal == cal2); 
}

it failed, telling me that this getInstance() method is actually not a singleton pattern getInstance() method but something else.

So, does getInstance() in general denote a singleton according the singleton pattern in Java or not? If so, what are the key wordings in the Java documentation to find out it is or is not a singleton? If not, how do I identify a singleton pattern in Java? Or is Calendar the only exception?

I'd not like to implement a unit test each time I meet a getInstance() call.

I have read this answer to "What is an efficient way to implement a singleton pattern in Java?", which would work exactly like in C#, which contradicts the Calendar implementation.

Community
  • 1
  • 1
Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
  • 3
    It's just a badly named method. It always creates a new instance and there should be some indication of that fact in the name or at least in the API doc. – biziclop Jun 15 '15 at 10:06
  • 1
    can only say `getInstance` in general is a factory method, it may return a singleton. There are no such keywords to tell if returned object is going to be a singleton. – Shailesh Aswal Jun 15 '15 at 10:09
  • Not singleton refers to current time. – Prashant Jun 15 '15 at 10:09
  • 1
    http://stackoverflow.com/questions/1673841/examples-of-gof-design-patterns-in-javas-core-libraries –  Jun 15 '15 at 11:28
  • It's a coincidence. `getInstance()` could mean get*An*Instance (factory) or get*The*Instance (singleton). Other patterns have methods like `visit()` and `create()` and `notify()` but it would be wrong to assume that the use of these methods imply the application of Visitor, Factory Method or Observer respectively. Patterns are more than just a method name. – Fuhrmanator Jun 15 '15 at 21:06

5 Answers5

10

Calendar is not a singleton, and each call to Calendar.getInstance(...) returns a different instance. The Javadoc doesn't say that each call will return the same instance, so you have no reason to assume that it will.

Calendar.getInstance(...) better fits the factory design pattern.

Looking at other examples of getInstance, such as Locale.getInstance(), you see that the Javadoc tells you if consecutive calls may return the same instance :

/**
 * Returns a <code>Locale</code> constructed from the given
 * <code>language</code>, <code>country</code> and
 * <code>variant</code>. If the same <code>Locale</code> instance
 * is available in the cache, then that instance is
 * returned. Otherwise, a new <code>Locale</code> instance is
 * created and cached.
 *
 * @param language lowercase two-letter ISO-639 code.
 * @param country uppercase two-letter ISO-3166 code.
 * @param variant vendor and browser specific code. See class description.
 * @return the <code>Locale</code> instance requested
 * @exception NullPointerException if any argument is null.
 */
static Locale getInstance(String language, String country, String variant)

Again, this is not a singleton, but the instances are cached, as the Javadoc says. Unless the Javadoc says so, you can expect each call to getInstance to return a different instance.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • The difference between the other locale-dependent classes and calendar though is that calendars are mutable and therefore absolutely mustn't be cached at all. It was a poor decision to use the same method name for two very different behaviours. – biziclop Jun 15 '15 at 10:15
  • 1
    @biziclop That's a good point. And since the Javadoc of Calendar says nothing about getInstance returning a cached instance or a singleton instance, we shouldn't assume either. I don't think we have to look at the implementation. If we do, this means the Javadoc is lacking. – Eran Jun 15 '15 at 10:18
  • To be precise, `Calendar.getInstance()` is a Static Factory method (from Josh Bloch) which is completely different from the GoF Factory Method pattern. – jaco0646 Nov 01 '18 at 17:58
2

Method getInstance() usually denotes a singleton in java, but it is not a rule engraved in the rock. The only way to tell for sure it is a singleton, you must either look at the documentation (if any) or better, the implementation.

Gauthier JACQUES
  • 655
  • 5
  • 15
  • 1
    *"One of the hardest things to explain is the relationship between patterns and examples. Most pattern descriptions include sample code examples, but it’s important to realize that the code examples aren’t the pattern."* -- [Martin Fowler](http://martinfowler.com/ieeeSoftware/patterns.pdf) – Fuhrmanator Jun 15 '15 at 21:01
1

Nope, if you look to the source code, you always get a new Calendar, the method getInstace() just determines which type of Calendar you will get:

public static Calendar More ...getInstance(TimeZone zone, Locale aLocale)
{
    return createCalendar(zone, aLocale);
}

And createCalendar:

private static Calendar More ...createCalendar(TimeZone zone, Locale aLocale)
{
    // If the specified locale is a Thai locale, returns a BuddhistCalendar instance.
    if ("th".equals(aLocale.getLanguage())
        && ("TH".equals(aLocale.getCountry()))) {
        return new sun.util.BuddhistCalendar(zone, aLocale);  // new Budhist
    } else if ("JP".equals(aLocale.getVariant())
               && "JP".equals(aLocale.getCountry())
               && "ja".equals(aLocale.getLanguage())) {
        return new JapaneseImperialCalendar(zone, aLocale); // new Japanese
    }

    // else create the default calendar
    return new GregorianCalendar(zone, aLocale);   // new Gregorian
}

How do I determine a singletton in java?

Singletton returns always same instance of an object, there are different ways, but usually you will have

  • Class attribute (the object to get the instance)
  • Private constructor to avoid new creations
  • Public getInstance method that check if the attribute is null to create it, and always same instance of the object...

Something like:

public class Singleton {
    // instance attribute
    private static Singleton INSTANCE = null;

    // private constructor
    private Singleton() {}

    // public get that checks instance and return it
    public static Singleton getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new Singleton();
        }
        return INSTANCE;
    }
}
Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
0

Since object returned by Calendar.getInstance() refer to some time (more specifically, the date and time on which that object was created), it should not be singleton. If this would be the case, all the objects would need to update their base date/time every time an operation is performed upon them.

However, as per my understanding, getInstance() is names so because it's a factory method. You don't need to create an instance directly, but you can use certain methods to point any date/time.

Aakash
  • 2,029
  • 14
  • 22
0

No.

getInstance() should be taken to indicate one thing and one thing only in Java, namely that you'll get an instance of the given class or one of its subclasses. Whether it fits a singleton or factory pattern differs wildly between classes and libraries.

In my experience getInstance() in standard library code java.* usually denotes a factory pattern, either configuring/subclassing a new instance with locale defaults (Calendar, NumberFormat and DateFormat comes to mind) or looking up a preexisting instance given some argument (Locale and Currency comes to mind). In third party library code there might be a tendency towards singleton-pattern.

As for the particulars of Calendar.getInstance(), the non-arg variant will give you an instance of a subclass of Calendar (probably one of GregorianCalendar, BuddhistCalendar or JapaneseCalendar) with time zone, depending on the default locale. The flavors with arguments will allow you to specify locale and/or time zone rather than have it pulled from the default.

If the instance returned is indeed a singleton or not, is cached or not or whatever is implementation specific. The documentation will usually indicate if the returned instance is mutable and if so if it can safely be shared between threads etc.

zrvan
  • 7,533
  • 1
  • 22
  • 23