假设我想实现为我提供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();
}
}
我毫不怀疑哪个更好,为什么?那边有什么区别?
答案 0 :(得分:3)
在非常高的级别,你可能会感到困惑,看起来他们都在做同样的任务。但是有很多不同之处。我一般都在回答这个问题。您可以根据应用程序(类型)了解优势。
Singleton仅在一个地方存储公共数据。它将大大简化程序的体系结构,并帮助您重用代码。单身人士可以让您更轻松地控制对象状态。这改善了代码共享和代码质量。因此,它变得更容易维护。 Singleton允许您覆盖,以防您想要覆盖它。可以使用Singleton类完成延迟加载。 Singleton更面向对象。静态对象存储在堆栈中,但是单个对象存储在堆中。
与Singleton相比,静态类很难测试(Singleton非常容易模拟。例如,在使用JUnit测试时)。如果您使用的是Spring或任何此类依赖注入框架,那么使用Singleton比使用Static更好。静态类不能传递给方法或继承。由于共享数据,静态类可能在并发环境中产生问题。最好不要在静态类中使用maintatin状态。您可以在此处http://en.wikipedia.org/wiki/Singleton_pattern或http://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;
}
}
我故意将静态工厂方法公开,以强调getInstance
和createInstance
之间的区别。
同样private
构造函数在它强制执行的模式中发挥重要作用,createInstance
/ getInstance
方法必须用于获取实例。
答案 5 :(得分:1)
简短的回答是,您不应该使用Singleton
方法。这是因为每次调用connection
方法时,您似乎都会返回一个新的getConnection
。如果这是你真正想要的,那么使用Singleton
类是没有意义的。你应该选择方法2。
答案很长,你似乎对Singleton
到底是什么感到困惑。 Singleton
类的目的是确保为给定的ClassLoader
创建给定类的只有一个对象,从而确保此类对象的状态是全局的。如果您的类不包含任何state
,那么您也可以使用仅包含static
方法的类。或者,如果您使用IoC
或Spring
等Guice
容器,则可以通过框架强制执行Singleton
,而不是将您的类明确设计为{Singleton
1}}。明确设计为Singleton
但没有任何状态的类确实没有多大意义。