Java: getInstance vs Static
Какова цель getInstance()
в Java?
Во время моего исследования я продолжаю читать, что getInstance()
помогает достичь шаблона проектирования Singleton (что означает только один экземпляр всей программы для моего понимания). Но не могу ли я использовать статику? Разве это не та точка статического?
Если бы у меня были только статические методы и поля, как бы это отличалось от использования getInstance()
? Есть ли "сфера" статичности? Например, один экземпляр для метода или класса?
И если они разные, в каких случаях я бы выбрал getInstance()
с помощью static?
Извиняюсь, если вопрос неясен, я уверен, что у меня что-то не хватает по этому вопросу, я просто не могу понять, что.
Спасибо за любой совет.
Ответы
Ответ 1
Статика не даст вам синглтон. Поскольку нет способа сделать класс верхнего уровня одиночным в Java, у вас есть методы getInstance, которые реализуют некоторую логику, чтобы быть уверенным, что есть только один экземпляр класса.
public class Singleton {
private static Singleton singleton;
private Singleton(){ }
public static synchronized Singleton getInstance( ) {
if (singleton == null)
singleton=new Singleton();
return singleton;
}
}
Посмотрите этот главный ответ: Статические классы в Java
Вышеприведенный код позволит создать только один экземпляр, но он чист, однако с Java 1.6 лучше создать singleton как таковой, поскольку он немного более изящный IMHO:
public enum MyEnumSingleton {
INSTANCE;
// other useful methods here
}
Источник: http://www.vogella.com/tutorials/DesignPatternSingleton/article.html
Ответ 2
Singleton
Синглтон позволяет использовать одну ссылку на объект Java. Например, вот один синглтон, который содержит число;
public class MySingleton {
private int myNumber;
private static MySingleton instance;
public static MySingleton getInstance() {
if (instance == null) {
instance = new MySingleton();
}
return instance;
}
private MySingleton() {}
public void setMyNumber(int myNumber) {
this.myNumber = myNumber;
}
public int getMyNumber() {
return myNumber;
}
}
Теперь мы собираемся установить значение этого числа в классе A:
public class A {
/*...*/
MySingleton mySingleton = MySingleton.getInstance();
mySingleton.setMyNumber(42);
/*...*/
}
Затем вы можете получить доступ к этому значению из другого класса:
public class B {
/*...*/
MySingleton mySingleton = MySingleton.getInstance();
int number = mySingleton.getMyNumber();
/*...*/
}
В этом классе переменная number
будет иметь значение 42. Это преимущество одиночного элемента над простым объектом:
Все значения, сохраненные в одноэлементном режиме, будут доступны из "Везде".
Статический класс
Цель разная, здесь преимущество состоит в том, чтобы использовать объект, не создавая его.
Например:
public static class MyStaticClass {
public static void sayHello() {
System.out.println("Hello");
}
}
Теперь вы можете использовать метод sayHello() из любых классов, вызвав:
MyStaticClass.sayHello();
Ответ 3
Точный метод реализации singleton, например, с помощью метода factory, называемый getInstance()
, не имеет отношения к вопросу, который представляет собой "статические методы vs singleton с методами экземпляра".
Классы сами по себе являются эффективными синглонами, поэтому из этого аспекта они похожи.
Основное отличие состоит в том, что статические методы не являются частью иерархии классов - они не наследуются, что означает, что параметр статического метода навсегда блокирует вас на использовании этого точного класса, и на него нельзя ссылаться каким-либо другим способом являясь реализацией некоторого интерфейса или суперкласса.
У экземпляров, однако, нет этой проблемы, поэтому вы можете использовать код, например:
class MySingleton implements SomeInterface {
...
}
SomeInterface instance = MySingleton.getInstance();
Ответ 4
Я предпочитаю использовать static
тоже, но иногда getInstance()
полезно иметь некоторые функции, которые будут связаны с объектом, в котором вы можете изменять переменные. если вы просто выполняете некоторые функции утилиты, которым не нужен экземпляр объекта, используйте static
.
Когда вы используете какие-то библиотеки, вы никогда не знаете, нуждается ли тело элемента в экземпляре класса. Поэтому многие классы библиотеки используют getInstance()
.
Ответ 5
Вместо того, чтобы проверять значение null, мне это немного лучше.
public class SingleObject {
//create an object of SingleObject
private static SingleObject instance = new SingleObject();
//make the constructor private so that this class cannot be
//instantiated
private SingleObject(){}
//Get the only object available
public static SingleObject getInstance(){
return instance;
}
}
Вызывается с...
public class SingletonPatternDemo {
public static void main(String[] args) {
//illegal construct
//Compile Time Error: The constructor SingleObject() is not visible
//SingleObject object = new SingleObject();
//Get the only object available
SingleObject object = SingleObject.getInstance();
}
}
Полный код от: http://www.tutorialspoint.com/design_pattern/singleton_pattern.htm
Ответ 6
Одна из упущенных причин использовать одноэлемент вместо статических переменных-членов класса состоит в том, что статические переменные-члены могут использовать пространство и время сбора мусора даже в том случае, если класс никогда не создается. Подумайте, сколько классов доступно вам в rt.jar и какая небольшая часть из них вы, вероятно, используете в любом конкретном приложении. Также подумайте, что использование getInstance гарантирует, что ваш "конструктор" будет запущен до того, как будет получен доступ к любой из переменных-членов. Я почти повсеместно вижу getInstance как синхронизированный, но я чувствую, что это плохая идея. Если кто-либо добавляет метод синхронной блокировки, вызывается Singleton.getInstance(). Unsynchronized() может быть бесполезно поднят.
private static Singleton instance = null;
private Singleton() {}
public final static Singleton getInstance() {
return (instance != null) ? instance : makeInstance();
}
private final static synchronized Singleton makeInstance() {
return ( instance != null ) ? instance : ( instance = new Singleton() );
}