Singleton和Static方法Java之间的混淆

时间:2015-05-16 13:50:29

标签: java class static singleton

假设我想实现为我提供Connection数据库连接的类。我可以使用下面给出的两个不同的代码捕捉实现相同的功能。

方法1:

class DBConnection1 {
    private static DBConnection1 instance = new DBConnection1();
    private DBConnection1(){

    }
    public static DBConnection1 getInstance(){
        return instance; 
    }
    public Connection getConnection(){
        Connection connection = null;
        //do my stuff to init the connection
        return connection;
    }
}

方法2:

class DBConnection2 {
    public static Connection getConnection(){
        Connection connection = null;
        //do my stuff to init the connection
        return connection;
    }
}

并访问上述方法,如

class TestConnection{
    public static void main(String[] args) {
        //using method 1
        Connection connection1 =  DBConnection1.getInstance().getConnection();
        //using method 1
        Connection connection2 =  DBConnection2.getConnection();
    }
}

我毫不怀疑哪个更好,为什么?那边有什么区别?

6 个答案:

答案 0 :(得分:3)

在非常高的级别,你可能会感到困惑,看起来他们都在做同样的任务。但是有很多不同之处。我一般都在回答这个问题。您可以根据应用程序(类型)了解优势。

Singleton仅在一个地方存储公共数据。它将大大简化程序的体系结构,并帮助您重用代码。单身人士可以让您更轻松地控制对象状态。这改善了代码共享和代码质量。因此,它变得更容易维护。 Singleton允许您覆盖,以防您想要覆盖它。可以使用Singleton类完成延迟加载。 Singleton更面向对象。静态对象存储在堆栈中,但是单个对象存储在堆中。

与Singleton相比,静态类很难测试(Singleton非常容易模拟。例如,在使用JUnit测试时)。如果您使用的是Spring或任何此类依赖注入框架,那么使用Singleton比使用Static更好。静态类不能传递给方法或继承。由于共享数据,静态类可能在并发环境中产生问题。最好不要在静态类中使用maintatin状态。您可以在此处http://en.wikipedia.org/wiki/Singleton_patternhttp://www.tutorialspoint.com/java/java_using_singleton.htm详细了解Singleton。

我看到静态类的唯一优势是它更快。仅当必须将一组函数保持在一起时才使用static。

答案 1 :(得分:2)

取决于您尝试实现的目标。例如,如果您确定在整个应用生命周期中都需要此连接 - 静态方法适合您。但如果你不确定 - 使用单身人士。但是在实际项目中,除了某种类型的utils方法之外,你可能不应该使用静态方法,因为与静态方法相比,singleton更灵活。

但至少还有一种你可能感兴趣的模式。Dependency injection。它可能比单身更复杂一点,但它再次灵活得多。如果在一个大项目中你可能需要一些由数据库提供的功能,并且你将使用一个类来访问它。但是后来的数据由两个数据库和两个具有相同接口的类分隔,相反,如果重写使用数据库的类的代码,则更改将在特定类中注入的实现。使用我所描述的依赖注入有很多好处,但我希望你能明白这一点。

答案 2 :(得分:1)

两种选择是等价的。但是,我更喜欢单例,因为将来更容易与子类化交换实现或覆盖行为。

另一个会产生更大差异的点是,是为每次使用创建新连接还是重用连接对象。这将对准备好的语句和提交/回滚产生很大的影响。

答案 3 :(得分:1)

如果您打算建立连接工厂,最好是实现method1。 因为您可以更改您工厂内部的代码,而对其他应用程序的影响很小。

小心重用连接,因为你可以共享上下文,这可能是你不想要的东西!

最好是从连接池中获取ConnectionFactory,一个连接,然后使用它,然后释放它......等等。

请参阅工厂模式:如果这是一个提供连接的连接工厂,最好查看Factory Method Pattern

答案 4 :(得分:1)

您混合了两种不同的模式,即Static Factory Method(与GoF Factory Method不同)和Singleton

静态工厂方法与创建实例有关。 Singleton模式用于确保Singleton类只有一个对象。

E.g。典型的静态工厂方法:

public DBConnection {

    private DBConnection(String param) {
        //...
    }

    public static DBConnection createConnection(String param) {
        return new DBConnection(param);
    }

}

注意,通常工厂方法称为create...getNewInstance或类似的强调,此方法将始终返回 new 实例。

与单身人士相同:

public DBConnection {

    private static DBConnection instance;

    private DBConnection(String param) {
        //...
    }

    public static DBConnection getInstance() {
        if(instance == null){
            instance = new DBConnection("fixed param!");
        }
        return instance;
    }

}

请注意,在懒惰地创建相同的实例后,总是会返回该实例。

然而,这些模式可以共存 - 例如单例可以使用静态工厂方法来创建实例:

public DBConnection {

    private static DBConnection instance;

    private DBConnection(String param) {
        //...
    }

    public static DBConnection createInstance(String param) {
        return new DBConnection(param);
    }

    public static DBConnection getInstance() {
        if(instance == null){
            instance = DBConnection.createInstance("param");
        }
        return instance;
    }

}

我故意将静态工厂方法公开,以强调getInstancecreateInstance之间的区别。

同样private构造函数在它强制执行的模式中发挥重要作用,createInstance / getInstance方法必须用于获取实例。

答案 5 :(得分:1)

简短的回答是,您不应该使用Singleton方法。这是因为每次调用connection方法时,您似乎都会返回一个新的getConnection。如果这是你真正想要的,那么使用Singleton类是没有意义的。你应该选择方法2。

答案很长,你似乎对Singleton到底是什么感到困惑。 Singleton类的目的是确保为给定的ClassLoader创建给定类的只有一个对象,从而确保此类对象的状态是全局的。如果您的类不包含任何state,那么您也可以使用仅包含static方法的类。或者,如果您使用IoCSpringGuice容器,则可以通过框架强制执行Singleton,而不是将您的类明确设计为{Singleton 1}}。明确设计为Singleton但没有任何状态的类确实没有多大意义。