Подтвердить что ты не робот

Как убедиться, что в JVM есть только один экземпляр класса?

Я разрабатываю шаблон дизайна, и я хочу убедиться, что это всего лишь один экземпляр класса в виртуальной машине Java, чтобы направить все запросы на какой-либо ресурс через одну точку, но я не знаю, возможно.

Я могу только думать о способе подсчета экземпляров класса и уничтожить весь экземпляр после его создания.

Это правильный подход? Если нет, есть ли другой способ?

4b9b3361

Ответ 1

Используйте шаблон singleton. Простейшая реализация состоит из private constructor и field для хранения ее результата и метода доступа static с таким именем, как getInstance().

Частное поле может быть назначено из статического блока инициализатора или, проще говоря, с помощью инициализатора. Метод getInstance() (который должен быть общедоступным) затем просто возвращает этот экземпляр,

public class Singleton {
    private static Singleton instance;

    /**
     * A private Constructor prevents any other class from
     * instantiating.
     */
    private Singleton() {
        // nothing to do this time
    }

    /**
     * The Static initializer constructs the instance at class
     * loading time; this is to simulate a more involved
     * construction process (it it were really simple, you'd just
     * use an initializer)
     */
    static {
        instance = new Singleton();
    }

    /** Static 'instance' method */
    public static Singleton getInstance() {
        return instance;
    }

    // other methods protected by singleton-ness would be here...
    /** A simple demo method */
    public String demoMethod() {
        return "demo";
    }
}

Обратите внимание, что метод использования "ленивой оценки" в методе getInstance() (который пропагандируется в шаблонах проектирования), не требуется в Java, потому что Java уже использует "ленивый загрузка. "Ваш одноэлементный класс, вероятно, не загрузится, если его getInstance() , поэтому нет смысла пытаться отложить построение синглтона до его необходимого с помощью getInstance() проверить одиночную переменную для null и создать синглтон есть.

Использование этого класса одинаково просто: просто получите и сохраните ссылку и вызовите на ней методы:

public class SingletonDemo {
    public static void main(String[] args) {
        Singleton tmp = Singleton.getInstance();
        tmp.demoMethod();
    }
}

Некоторые комментаторы считают, что синглтон должен также предоставить публичный финал clone(), который просто генерирует исключение, чтобы избежать подклассов, которые "обманывают" и clone() синглтон. Однако ясно, что класс с только частным конструктором не может быть подклассом, поэтому эта паранойя не представляется необходимой.

Ответ 2

Вам нужен шаблон Singleton. Существует отличная дискуссия о том, как правильно это реализовать. Если вы сделаете это правильно, будет только один экземпляр класса.

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

Ответ 3

Существует школа мысли, которая рассматривает шаблон Singleton на самом деле как анти-шаблон.

Учитывая класс A, в котором вы только желаете, есть альтернатива - иметь класс builder или factory, который сам ограничивает создание числа объектов класса A, и это может быть простым счетчик. Преимущество состоит в том, что классу A больше не нужно беспокоиться об этом, он концентрируется на своей реальной цели. Каждый класс, который его использует, больше не должен беспокоиться о том, что он является одним из них (не более вызовов getInstance()).

Ответ 4

Это хорошо известный шаблон Singleton: вы можете реализовать это следующим образом:

public class SingletonClass {

    //this field contains the single instance every initialized.
    private static final instance = new SingletonClass();

    //constructor *must* be private, otherwise other classes can make an instance as well
    private SingletonClass () {
        //initialize
    }

    //this is the method to obtain the single instance
    public static SingletonClass getInstance () {
        return instance;
    }

}

Затем вы вызываете экземпляр (например, вы создаете не одиночный элемент) с помощью:

SingletonClass.getInstance();

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

Ответ 5

Использовать перечисление. В Java перечисление - единственный верный способ создания singleton. Частные конструкторы могут быть все еще вызваны через отражение.

См. этот вопрос StackOverflow для получения дополнительной информации: Реализация Singleton с Enum (на Java)

Обсуждение: http://javarevisited.blogspot.com/2012/07/why-enum-singleton-are-better-in-java.html

Ответ 6

Я могу только думать о способе подсчета экземпляров класса и уничтожить все экземпляры после их создания. Правильно ли это? Если нет, есть ли другой способ?

Правильный технический подход состоит в том, чтобы объявить все конструкторы для класса как private, чтобы экземпляры класса могли создаваться только самим классом. Затем вы кодируете класс только когда-либо создаете один экземпляр.

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

Ответ 7

Я предпочитаю ленивый одноэлементный класс, который переопределяет метод readResolve.

Для классов Serializable и Externalizable метод readResolve позволяет классу заменять/разрешать объект, считанный из потока, прежде чем он будет возвращен вызывающему. Внедряя метод readResolve, класс может напрямую контролировать типы и экземпляры своих дескрипторов своих экземпляров.

Lazy singleton с помощью /Initialization-on-demand_holder_idiom:

public final class  LazySingleton {
    private LazySingleton() {}
    public static LazySingleton getInstance() {
        return LazyHolder.INSTANCE;
    }
    private static class LazyHolder {
        private static final LazySingleton INSTANCE = new LazySingleton();
    }
    private Object readResolve()  {
        return LazyHolder.INSTANCE;
    }
}

Ключевые примечания:

  • final ключевое слово запрещает расширение этого класса путем подклассификации Конструктор
  • private запрещает создание прямого объекта с помощью оператора new в классах вызывающего абонента
  • readResolve запрещает создание нескольких экземпляров класса во время де-сериализации объекта

Ответ 8

Для этого вам нужно использовать singleton pattern, я просто размещаю демо-код для того, что может быть полезно для вашего понимания.

Например: если мне нужен только один объект для этого класса Connect:

public final class Connect {

    private Connect() {}

    private volatile static Connect connect = null;

    public static Connect getinstance() {
        if(connect == null) {
            synchronized (Connect.class) {
                connect = new Connect();
            }
        }
        return connect;
    }
}

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

Ответ 9

class A{
    private A(){

    }
    public static A creator(A obj){
        A ob=new A();
        return ob;
    }
    void test(){
        System.out.println("The method is called");
    }
}

class Demo{
    public static void main(String[] args){
        A ob=null;
        ob=A.creator(ob);
        ob.test();
    }
}