日期:2014-05-19  浏览次数:20756 次

探讨单例模式的利与弊
最近公司的一个项目中大量的使用了java 单利模式,例如:

public class Test{

private Test instance;

private Test(){
}

public Test getInstance()
{
if(null == instance)
{
instance = new Test();
}
return instance;
}

}

我总感觉大量使用单利模式有点怪怪的感觉。请问各位大狭,一般在什么情况下使用单利模式呢?使用单利模式的好处有哪些呢?有哪些坏处呢和隐患呢?

谢谢了!
------最佳解决方案--------------------
单例模式并不怪,而且很常用。

当然,单例模式不适用于对象需要维护状态的情况,所以值对象重来不是单例。

不过你贴出来的代码,是存在问题的;企图懒加载而又缺乏同步保护。
------其他解决方案--------------------
 饿汉式单例类在自己被加载时就将自己实例化。即便加载器是静态的,在饿汉式单例
 类被加载时仍会将自己实例化。单从资源利用效率角度来讲,这个比懒汉式单例类稍差些。
 从速度和反应时间角度来讲,则比懒汉式单例类稍好些。然而,懒汉式单例类在实例化时,
 必须处理好在多个线程同时首次引用此类时的访问限制问题,特别是当单例类作为资源控
 制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费时间。这意味着出现
 多线程同时首次引用此类的机率变得较大。  
     饿汉式单例类可以在 Java 语言内实现,但不易在 C++内实现,因为静态初始化在 C++
 里没有固定的顺序,因而静态的 m_instance 变量的初始化与类的加载顺序没有保证,可能
 会出问题。饿汉式单例类更符合 Java 语言本身的特点。
------其他解决方案--------------------
引用:
你这算单例,但是错了。。。
帮你改了下,这样性能最好。。。


他是想用懒加载,不用一开始就加载进去!
不过楼主和2楼都有一个疏忽,就是没有把instance变量和getInstance()方法声明成static的,否者就不算单例了。


引用:
不过你贴出来的代码,是存在问题的;企图懒加载而又缺乏同步保护。


1楼发现的问题的确存在,不过如果Test中没什么冲突的属性,也无所谓了,反正没同步最多就是多产生几个Test实例,最后instance还是只会指向一个。
至于楼主是选择2楼的一开始就加载,还是原来的懒加载,就看具体情况分析了!


------其他解决方案--------------------
单例模式能实现信息共享(有点全局变量的意思,便于同步控制),而一个线程需要独立的一份信息的时候就不能用单例
------其他解决方案--------------------
单例模式很好呀:
就框架而言Spring是管理单利最好不过的了,默认Spring帮你注入的都是采用单例的
另外单例模式比较节省资源,想想,如果每次去调用同一个方法,都要去new,那资源有多浪费,虽然说java有他一套的资源回收,但是学过java的人都知道,他的回收都是不定时,不可控制的,那单例模式就是可以避免在执行同一个方法时消耗过大,秉承一个原则:上下环境有,我就用环境的,没有,我才自己创建.好比吃饭用的碗筷一样,家里有就拿出来用就是了,没必要每次吃饭都上一次超市买一副回来再吃.
呵呵,我是用我的话说出来的,可能总结的不好,但还是凑合着看吧,大概重点就是这样了

------其他解决方案--------------------
贴出的代码并没错,只是这种方式在多线程同步时是不安全的,这种俗称懒汉式单例,另一种叫饿汉式单例,即声明时就直接new了:private Test instance = new Test();
------其他解决方案--------------------
你这算单例,但是错了。。。
帮你改了下,这样性能最好。。。
public class Test{

private Test instance = new Test();

private Test(){
}

public Test getInstance()
{
return instance;
}

}

------其他解决方案--------------------
sorry ,是有static的,我用记事本随便敲的这几行代码就忘了加了
------其他解决方案--------------------
引用:
单例模式并不怪,而且很常用。

当然,单例模式不适用于对象需要维护状态的情况,所以值对象重来不是单例。

不过你贴出来的代码,是存在问题的;企图懒加载而又缺乏同步保护。


这样可以了吧?
package src.com.fornew.tvm.unitmodule.valuecardreader.model;

public class Test {

private static Test instance;

private Test() {
}

public static Test getInstance() {
if (null == instance) {
synchronized(Test.class){
if(instance==null){