getInstance()是否根据单例模式表示单例?

时间:2015-06-15 10:04:52

标签: java design-patterns

之前曾与C#合作过,我考虑过

Calendar cal = Calendar.getInstance();

根据GoF Singleton pattern (Wikipedia)成为单身方法,我想知道如何创建两个日历,因为Date已被弃用。

来自文档

  

使用默认时区和区域设置获取日历。

和重载

getInstance(TimeZone zone)
getInstance(Locale aLocale)

在我看来,这是对单例模式的概括,以便为每个时区和区域设置创建一个单例。但是我想在同一时区里有两个日历。

然而,当我进行测试时

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

它失败了,告诉我这个getInstance()方法实际上不是单一模式getInstance()方法,而是其他方法。

那么,一般来说getInstance()是否根据Java中的单例模式表示单例?如果是这样,Java文档中的关键字是什么来找出它? > 或不是单身人士?如果没有,我如何识别Java中的单例模式?或者Calendar是唯一的例外吗?

每次遇到getInstance()电话时,我都不想实施单元测试。

我看过this answer to "What is an efficient way to implement a singleton pattern in Java?",它与C#完全相同,与Calendar实现相矛盾。

5 个答案:

答案 0 :(得分:7)

Calendar不是单例,每次调用Calendar.getInstance(...)都会返回不同的实例。 Javadoc并没有说每个调用都会返回相同的实例,所以你没有理由认为它会。

Calendar.getInstance(...)更符合工厂设计模式。

查看getInstance的其他示例,例如Locale.getInstance(),您会看到Javadoc告诉您连续调用是否可能返回相同的实例:

/**
 * 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)

同样,这不是一个单例,但实例是缓存的,正如Javadoc所说。除非Javadoc这样说,否则每次调用getInstance都会返回一个不同的实例。

答案 1 :(得分:1)

方法"config": { "webpack_server_port": "8080", "mockup_server_port": "3000" } 通常表示java中的单例,但它不是刻在岩石中的规则。要确定它是单例的唯一方法,你必须查看文档(如果有的话)或更好的实现。

答案 2 :(得分:0)

不,如果您查看the source code,您总是得到new Calendar,方法getInstace()只会确定您将获得的Calendar类型:

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

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
}

如何在java中确定单例?

Singletton总是返回一个对象的同一个实例,有不同的方式,但通常你会有

  • 类属性(获取实例的对象)
  • 私人构造函数,以避免新的创作
  • 公共getInstance方法,用于检查属性是否为null以创建它,并且始终是对象的相同实例...

类似的东西:

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

答案 3 :(得分:0)

由于Calendar.getInstance()返回的对象引用了一些时间(更具体地说,是创建该对象的日期和时间),因此它不应该是单例。如果是这种情况,那么每次对它们执行操作时,所有对象都需要更新它们的基准日期/时间。

但是,根据我的理解,getInstance()是名称,因为它是一种工厂方法。您不需要直接创建实例,但可以使用某些方法指向任何日期/时间。

答案 4 :(得分:0)

没有

getInstance()应仅用于表示Java中的一件事和一件事,即您将获得给定类或其子类之一的实例。它是否适合单例或工厂模式在类和库之间存在很大差异。

根据我的经验getInstance()标准库代码java.*通常表示工厂模式,使用语言环境默认值(CalendarNumberFormat和{配置/子类化新实例考虑到{1}}或者在给出一些参数的情况下查找预先存在的实例(DateFormatLocale会浮现在脑海中)。 在第三方库代码中,可能存在单例模式的倾向。

至于Currency的详细信息,非arg变体将为您提供Calendar.getInstance()的子类的实例(可能是CalendarGregorianCalendar或{ {1}})带时区,具体取决于默认语言环境。带参数的flavor将允许您指定区域设置和/或时区,而不是从默认区域中提取它。

如果返回的实例确实是单例或不是单例,则是否缓存,或者是特定于实现的任何内容。文档通常会指出返回的实例是否可变,如果可以,则可以安全地在线程之间共享等。