关于设计模式:Java:getInstance vs Static

Java: getInstance vs Static

Java中EDOCX1 0的目的是什么?

在我的研究中,我一直在读到getInstance()有助于实现单例设计模式(据我所知,这意味着整个程序只有一个实例)。但我不能只用静电吗?这不是静电的全部意义吗?

如果我只有静态方法和字段,那么它与使用getInstance()有什么不同?是否存在静态的"范围"?例如,每个方法或类有一个实例?

如果它们不同,在什么情况下我会选择getInstance()而不是使用static?

我很抱歉,如果问题不清楚,我确信我在主题上遗漏了一些东西,我就是搞不清是什么。

谢谢你的建议。


静态将不会给你一个单件。由于在爪哇无法生成顶级类A单体,所以您有GET实例方法,它将实现某种逻辑,以确保类只有一个实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
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,最好是创建单体,因为它稍微有点雅致:

1
2
3
4
5
public enum MyEnumSingleton {
    INSTANCE;

    // other useful methods here
}

资料来源:http://www.vogella.com/tutorials/designpatternsingleton/article.html


独生子女

单元格允许您使用Java对象的单个引用。例如,这里是一个包含数字的单例数;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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类中设置这个数字的值:

1
2
3
4
5
6
public class A {
    /*...*/
    MySingleton mySingleton = MySingleton.getInstance();
    mySingleton.setMyNumber(42);
    /*...*/
}

然后,您可以从另一个类访问该值:

1
2
3
4
5
6
public class B {
    /*...*/
    MySingleton mySingleton = MySingleton.getInstance();
    int number = mySingleton.getMyNumber();
    /*...*/
}

在这个类中,number变量的值为42。这是单例程序相对于简单对象的优势:

All the values stored in the singleton will be accessible from
"everywhere".

静态类

目的是不同的,这里的优势是使用一个对象而不必创建它。

例如:

1
2
3
4
5
public static class MyStaticClass {
    public static void sayHello() {
        System.out.println("Hello");
    }
}

现在,您可以通过调用以下命令从任何类中使用sayhello()方法:

1
MyStaticClass.sayHello();


例如,使用名为getInstance()的工厂方法来实现单例的确切方法与"静态方法与具有实例方法的单例方法"的问题不太相关。

类本身实际上是单例的,所以从这个方面来说它们是相似的。

主要的区别在于静态方法不是类层次结构的一部分——它们不是继承的,这意味着静态方法选项将永远锁定您使用精确的类,并且不能以任何其他方式引用它,例如某个接口或超级类的实现。

但是,实例不存在此问题,因此可以编写代码,例如:

1
2
3
4
5
class MySingleton implements SomeInterface {
    ...
}

SomeInterface instance = MySingleton.getInstance();

我也喜欢使用static,但有时getInstance()有助于具有一些与对象相关的函数,您可以在其中修改变量。如果只是生成一些不需要对象实例的util函数,请使用static

当您使用某人的库时,您永远不知道函数体是否需要类实例。这就是为什么许多库类使用getInstance()的原因。


使用singleton而不是静态类成员变量的一个被忽视的原因是静态成员变量可能使用空间和垃圾回收器时间,即使在从未实例化类的情况下也是如此。考虑在rt.jar中有多少类可供您使用,以及在任何给定的应用程序中可能使用它们中的哪一小部分。还要考虑使用getInstance确保您的"构造函数"在访问任何成员变量之前已经运行。我几乎普遍认为GetInstance是同步的,但我觉得这是个坏主意。如果有人向singleton.getInstance()添加了一个同步的阻塞方法调用,那么不同步的()可能会被不必要地延迟。

1
2
3
4
5
6
7
8
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() );
}

我不检查空值,而是更喜欢这个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
    }
}

打电话给…

1
2
3
4
5
6
7
8
9
10
11
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