Частный конструктор, инициализированный общедоступным методом

Я столкнулся с классом с частным конструктором, но объект возвращается другим общедоступным методом при вызове частного конструктора. В чем может быть преимущество такой конструкции, когда мы могли бы сделать конструктор общедоступным?

public final class TokenTable {

    static public int errorToken = 0; 
    static public int timesToken = 1;
    static public int divToken = 2;
    static public int plusToken = 11;
    ......
    ......

    private final HashMap<String, Integer> keywordMap = new HashMap();
    private final HashMap<String, Integer> operationMap = new HashMap();

    private TokenTable() {

        operationMap.put("*", timesToken);
        operationMap.put("/", divToken);
        operationMap.put("+", plusToken);
        ....



    }


    static public TokenTable getInstance() {

            LexTokenTabInstance = new TokenTable();
            return LexTokenTabInstance;
    }

}

person Shan    schedule 21.05.2013    source источник
comment
Должен сказать, я немного разочарован тем, что большинство ответов здесь вызывают синглтоны. Я предполагаю, что это имя getInstance() (которое является одним из наиболее распространенных имен для одноэлементного геттера)... но все же.   -  person cHao    schedule 21.05.2013
comment
@cHao Если вас не устраивают текущие ответы, почему бы вам не создать свои собственные? Если вы считаете, что есть лучший ответ, чем предоставленные, мне было бы любопытно его прочитать.   -  person Supericy    schedule 21.05.2013
comment
@Supericy: Потому что здесь есть два хороших, которые уже говорят почти то же, что и я. Меня угнетают другие.   -  person cHao    schedule 21.05.2013
comment
Вы также можете взглянуть на этот ответ stackoverflow.com/questions/16620832/, который имеет отношение к шаблону статической фабрики.   -  person nakosspy    schedule 21.05.2013


Ответы (5)


Это называется шаблоном Factory. Ознакомьтесь с описанием здесь — Factory Design Pattern.

Есть несколько преимуществ:

  • у вас может быть несколько именованных фабричных методов для создания разных вариантов объекта, которые могут допускать перегрузку с одним и тем же набором типов параметров.
  • вы можете вернуть синглтон, если это необходимо, или, возможно, вернуть один из кешированных экземпляров
  • если не нужно использовать new
  • при использовании дженериков общий тип выводится компилятором, поэтому не нужно использовать оператор <>
  • вы можете вернуть интерфейс вместо конкретного класса
  • позволяет выполнять инициализацию перед конструктором (например, если инициализация должна быть выполнена до вызова конструктора базового класса)

Чтобы было ясно, в приведенном выше примере кажется, что это было сделано просто как «хорошая практика», поскольку ни одна из вышеперечисленных возможностей не использовалась (кроме того, что вам не нужно использовать «новый»).

person John B    schedule 21.05.2013
comment
Вероятно, следует отметить, что там, где вам не понадобятся никакие из этих преимуществ, обычный публичный конструктор несет немного меньше ментального багажа. то есть: не превращайте все в фабрику только потому, что это шикарнее. :) - person cHao; 21.05.2013

Это называется фабричным методом. Фабричный метод имеет много преимуществ перед конструктором:

  • у него есть имя (и несколько фабричных методов могут иметь разные имена)
  • он позволяет вернуть кешированный экземпляр вместо нового экземпляра
  • он позволяет вернуть экземпляр подкласса вместо фактического класса
  • и т.п.
person JB Nizet    schedule 21.05.2013

Основное преимущество в том, что никто не может создать экземпляр, кроме как с помощью статического getInstance метода.

Таким образом, вы можете убедиться, что создан только один экземпляр, как шаблон проектирования Singelton< /а>

person BobTheBuilder    schedule 21.05.2013

Основной причиной сокрытия конструктора класса является контроль над тем, как создаются объекты этого класса. Типичным примером этого является шаблон Singleton, где создается экземпляр только одного объекта класса.

Чтобы контролировать это, пользователь обращается к статическому методу, который будет обращаться к частному конструктору, если объект не создан, или же вернуть ссылку на уже созданный объект:

public class SingletonDemo {
    private static volatile SingletonDemo instance = null;

    private SingletonDemo() {       }

    public static SingletonDemo getInstance() {
            if (instance == null) {
                    synchronized (SingletonDemo.class){
                            if (instance == null) {
                                    instance = new SingletonDemo();
                            }
                  }
            }
            return instance;
    }
}  

Другие примеры см. в шаблонах Factory в целом: http://en.wikipedia.org/wiki/Factory_method_pattern< /а>

person Andrew Martin    schedule 21.05.2013

Если вы не хотите защищать создание нескольких экземпляров вне класса, вы можете создать частный конструктор.
Это полезно при создании одного экземпляра.
Вы можете сделать это следующим образом (нетерпеливая загрузка):

private static final TokenTable tokenTable = new TokenTable();

static public TokenTable getInstance() {

          return tokenTable;
    }

Или вы можете сделать это так (отложенная загрузка):

private static TokenTable tokenTable;

static public TokenTable getInstance() {
         if(null == tokenTable){
         tokenTable = new TokenTable(); 
         }
          return tokenTable;
    }
person Shreyos Adikari    schedule 21.05.2013
comment
Обратите внимание, что пример ленивой загрузки не является потокобезопасным. :P Обычно вы помечаете функцию как synchronized или явно синхронизируете класс или что-то в этом роде. - person cHao; 21.05.2013
comment
Хорошо, Чао, спасибо за эту ценную информацию. - person Shreyos Adikari; 21.05.2013