`
步行者
  • 浏览: 169830 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

为什么需要Singleton

阅读更多

为什么需要 单例设计模式(Singleton)?

像下面的一个单例

 

public class Singleton {
	private static Singleton instance = null;
	private Singleton(){};
	public static synchronized Singleton getInstance(){
		if(instance == null)
			instance = new Singleton();
		return instance;
	}
	public void doSomething(){
		//do something
	}
}


它要实现的主要目标,就是在一个应用中只维护一个Singleton实例

但一个类在一个应用中也是唯一的,为什么不能直接以类作为单例呢?

 

public final class AnotherSingleton{
	private AnotherSingleton(){}
	public static synchronized void doSomething(){
		//do something
	}
}

 

把类的所有方法都改为静态方法,

所有属性都改为静态属性(我们可以把

静态属性看成类的内部状态),

但是不允许实例化,

对类的操作相当于对单例的操作

而且类也可以维护内部状态(通过静态私有属性)

这完全满足了单例的要求。

不知道为什么需要单例模式。。。


因为我想不出来在什么情况下 单例可以满足需求

而 类 不能。

 

 

 

分享到:
评论
66 楼 步行者 2009-06-08  
hoorace 写道
你这个只是一个简单的例子而已,如果在复杂的配置中,调用了N多的api,有的api不是static式的,不能写在static的方法中,这样,为了保证内存中的类只有一份,就需要singleton了!


api不是static的 ,就不能static方法里调用这个api吗?
不是吧。。
65 楼 步行者 2009-06-08  
moonranger 写道
Testability...


why not。。
64 楼 hoorace 2009-06-08  
你这个只是一个简单的例子而已,如果在复杂的配置中,调用了N多的api,有的api不是static式的,不能写在static的方法中,这样,为了保证内存中的类只有一份,就需要singleton了!
63 楼 moonranger 2009-06-08  
Testability...
62 楼 步行者 2009-06-08  
<div class="quote_title">scvptz 写道</div>
<div class="quote_div">
<div class="quote_title">步行者 写道</div>
<div class="quote_div">
<p><span style="font-size: 13px;">因为我想不出来在什么情况下 单例可以满足需求</span></p>
<p><span style="font-size: small;">而 类 不能。</span></p>
</div>
<p>你的追求仅仅只满足于实现需求吗?</p>
<p>如果静态方法在多处被调用,将来某个时候,你希望它不是单例了,那么修改的代码量就非常大了。</p>
<p>如果把单例模式和工厂模式结合起来用,这个时候,需要修改的只是工厂内部的实现,调用单例的地方都不用修改。</p>
<p>更进一步,使用spring来注入,那么连工厂方法也不用写,只需要改一下配置,就可以灵活的在单例和实例之间切换了。</p>
<p> </p>
</div>
<p> </p>
<p>你说的都是针对对象得特性,类当然不能满足</p>
<p><br>类就是全局唯一的,又可以通过静态属性维护内部状态,他是天然的Singleton,但它不是对象,</p>
<p>至于跟工厂模式得结合 ,我觉得不会出现问题,你只需要把工厂类构造成Singleton就行了</p>
<p> </p>
61 楼 scvptz 2009-06-08  
<div class="quote_title">步行者 写道</div>
<div class="quote_div">
<p><span style="font-size: 13px;">因为我想不出来在什么情况下 单例可以满足需求</span></p>
<p><span style="font-size: small;">而 类 不能。</span></p>
</div>
<p>你的追求仅仅只满足于实现需求吗?</p>
<p>如果静态方法在多处被调用,将来某个时候,你希望它不是单例了,那么修改的代码量就非常大了。</p>
<p>如果把单例模式和工厂模式结合起来用,这个时候,需要修改的只是工厂内部的实现,调用单例的地方都不用修改。</p>
<p>更进一步,使用spring来注入,那么连工厂方法也不用写,只需要改一下配置,就可以灵活的在单例和实例之间切换了。</p>
<p> </p>
60 楼 kaka11 2009-06-08  
Singleton如果序列化的话,还要注意序列化问题:
/**
 * @author   kakachen
 */
public class SingletonSer implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -892694328982110567L;

	public static final SingletonSer INSTANCE = new SingletonSer();
	
	private SingletonSer() {

	}

	private Object readResolve() throws ObjectStreamException {
		return INSTANCE;
	}
}

这在<<effective java>>中都有讲到,不过该书的第2版中还讲了如果依赖于这种方法遇到了一些带有引用类型的实例变量必须把它置成transient,不然就有可能被攻击,具体的可以看该书第77条.所以如果是jdk1.5以上优先使用enum来作为序列化的Singleton.
59 楼 步行者 2009-06-08  
kaka11 写道
至于Singleton的同步问题DCL好象是有问题的,所以我推荐使用Bob Lee的Lazy写法:
public class NewSingleton {
	private static class SingletonHolder {
		static NewSingleton INSTANCE = new NewSingleton();
	}

	public static NewSingleton getInstance() {
		return SingletonHolder.INSTANCE;
	}
}


应该加一个 private 构造器
58 楼 kaka11 2009-06-08  
至于Singleton的同步问题DCL好象是有问题的,所以我推荐使用Bob Lee的Lazy写法:
public class NewSingleton {
	private static class SingletonHolder {
		static NewSingleton INSTANCE = new NewSingleton();
	}

	public static NewSingleton getInstance() {
		return SingletonHolder.INSTANCE;
	}
}
57 楼 kaka11 2009-06-08  
步行者 写道
redhat 写道
另外,一般StringUtils是abstract final的,否则不能保证是单例,我可以直接new 一个出来(这是一个漏洞),参见spring的StringUtils。

还有
abstract final 使不能通过编译的。

对于工具类限制有两种方法:
1.加abstract.
2.使构造函数变成private.
个人更推荐第二种方式.
56 楼 步行者 2009-06-08  
redhat 写道
另外,一般StringUtils是abstract final的,否则不能保证是单例,我可以直接new 一个出来(这是一个漏洞),参见spring的StringUtils。

还有
abstract final 使不能通过编译的。
55 楼 zhaomingzm_23 2009-06-08  
步行者 写道
zhaomingzm_23 写道
楼主要注意多线程的问题
还有synchronized修饰的方法最好改成
用锁(ReentrantLock)的双判断模式效果会更好
package singleton;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Singleton {

	/** unique instance */
	private static Singleton sInstance = null;

     /** static lock */
	private static Lock lock = new ReentrantLock();
	
    /** 
	 * Private constuctor
	 */
	private Singleton() {
		super();
	}

	/** 
	 * Get the unique instance of this class.
	 */
	public static Singleton getUniqueInstance() {
		
		if (sInstance == null) {
			lock.lock(); //lock need times.
			try{
				if(sInstance == null){
					sInstance = new Singleton();
				}
			}finally{
				lock.unlock();
			}
		}

		return sInstance;

	}
//.. other code.
}


你好 多线程问题很重要
为什么synchronized修饰的方法改成
用锁(ReentrantLock)的双判断模式效果会更好?
synchronized 会引起线程不同步 或 效率问题吗




这个问题就是效率问题了,你可以参考下jdk1.5 中ConcurrentHashMap 的文档注释,说的很详细。
54 楼 步行者 2009-06-08  
redhat 写道
首先要看看你的类是否需要其他oo特性,简单来说,一些工具类,如StringUtils等,不需要太多继承,也不需要其他继承等,那么就没有必要,就看你的是否需要。

另外,一般StringUtils是abstract final的,否则不能保证是单例,我可以直接new 一个出来(这是一个漏洞),参见spring的StringUtils。


AnotherSingleton 构造函数是 private 的,不能new出来
StringUtils 和 我这个类 有区别
StringUtils 没有内部状态,它就是把管局String的工具函数打包了
而 AnotherSingleton 是有内部状态的(私有静态属性)。
53 楼 步行者 2009-06-08  
zhaomingzm_23 写道
楼主要注意多线程的问题
还有synchronized修饰的方法最好改成
用锁(ReentrantLock)的双判断模式效果会更好
package singleton;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Singleton {

	/** unique instance */
	private static Singleton sInstance = null;

     /** static lock */
	private static Lock lock = new ReentrantLock();
	
    /** 
	 * Private constuctor
	 */
	private Singleton() {
		super();
	}

	/** 
	 * Get the unique instance of this class.
	 */
	public static Singleton getUniqueInstance() {
		
		if (sInstance == null) {
			lock.lock(); //lock need times.
			try{
				if(sInstance == null){
					sInstance = new Singleton();
				}
			}finally{
				lock.unlock();
			}
		}

		return sInstance;

	}
//.. other code.
}


你好 多线程问题很重要
为什么synchronized修饰的方法改成
用锁(ReentrantLock)的双判断模式效果会更好?
synchronized 会引起线程不同步 或 效率问题吗


52 楼 redhat 2009-06-08  
首先要看看你的类是否需要其他oo特性,简单来说,一些工具类,如StringUtils等,不需要太多继承,也不需要其他继承等,那么就没有必要,就看你的是否需要。

另外,一般StringUtils是abstract final的,否则不能保证是单例,我可以直接new 一个出来(这是一个漏洞),参见spring的StringUtils。
51 楼 zhaomingzm_23 2009-06-08  
楼主要注意多线程的问题
还有synchronized修饰的方法最好改成
用锁(ReentrantLock)的双判断模式效果会更好
package singleton;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Singleton {

	/** unique instance */
	private static Singleton sInstance = null;

     /** static lock */
	private static Lock lock = new ReentrantLock();
	
    /** 
	 * Private constuctor
	 */
	private Singleton() {
		super();
	}

	/** 
	 * Get the unique instance of this class.
	 */
	public static Singleton getUniqueInstance() {
		
		if (sInstance == null) {
			lock.lock(); //lock need times.
			try{
				if(sInstance == null){
					sInstance = new Singleton();
				}
			}finally{
				lock.unlock();
			}
		}

		return sInstance;

	}
//.. other code.
}
50 楼 redhat 2009-06-08  
首先要看看你的类是否需要其他oo特性,简单来说,一些工具类,如StringUtils等,不需要太多继承,也不需要其他继承等,那么就没有必要,就看你的是否需要。

另外,一般StringUtils是abstract final的,否则不能保证是单例,我可以直接new 一个出来(这是一个漏洞),参见spring的StringUtils。
49 楼 步行者 2009-06-08  
Saito 写道
ms .. 你没看懂我给你的回复. .

  请看你引用我的回复.. 

  我再次强调. AnotherSingleton 能不能实例化没关系.. 理由同Math ..

  似乎楼主还在为自己创造了一个新的模式而欣喜 . 一种介乎与Singleton跟Monostate的新模式. 实际上掉入了Monostate 能实例化跟不能实例化的怪圈. 实际上Monostate没人傻到要去实例化他. 当然. 你去private他也是有好处的. 告诫别人别做傻事.


我问你 Math 有内部私有状态吗
其他的不多说了

我不是创建模式 而是讨论模式

48 楼 Saito 2009-06-08  
ms .. 你没看懂我给你的回复. .

  请看你引用我的回复.. 

  我再次强调. AnotherSingleton 能不能实例化没关系.. 理由同Math ..

  似乎楼主还在为自己创造了一个新的模式而欣喜 . 一种介乎与Singleton跟Monostate的新模式. 实际上掉入了Monostate 能实例化跟不能实例化的怪圈. 实际上Monostate没人傻到要去实例化他. 当然. 你去private他也是有好处的. 告诫别人别做傻事.
47 楼 步行者 2009-06-08  
Saito 写道


   你的AnotherSingleton无论私有或共有. 实际上是没有任何意义的.

   既然他们是相同的. 那你去实例化多个有什么意义.  唯一的好处是给别人提醒一下. 别浪费. 但是一般看了api的人应该都不会那么傻. .

   就跟你见过有人有事没事就实例化几个Math么?

   全局的应用状态. 一般这样来说. 对象是可以保存状态的. 而Math这种东西一般没有状态. 这也是Singleton跟Monostate的最根本区别.  Singleton我是用来用他那个instance的. 而Monostate.我用的只是那个class.  .




注意 AnotherSingleton 不能实例化
而 MonoState 是可以用来实例化的
如果MonoState 不能实例化 那他就和
AnotherSingleton 一样的了

关于AnotherSingleton 和MonoState
的设计动机 请看我上次给你的回复

相关推荐

    Singleton

    只有在INSTANCE为null时,才进行同步,这样大多数情况下都不需要同步。 ```java public class Singleton { private volatile static Singleton INSTANCE; private Singleton() {} public static Singleton ...

    C++完美实现Singleton模式

    如果项目中有多个Singleton类需要实现,那么重复的代码将会增多。为了解决这个问题,可以通过模板化Singleton类来减少代码量: ```cpp #pragma once #include using namespace std; using namespace C2217::Win32;...

    Qt qml Singleton 单例模式

    - 如果Singleton需要在C++中初始化,可以使用`setObject`方法在C++侧设置Singleton的实例。 综上所述,Qt Qml的Singleton模式为全局共享对象提供了方便,使得在Qml环境中管理和访问同一对象变得简单。通过C++和Qml...

    C++ 实现的singleton 模式

    // 如果有需要初始化的数据,可以在这里声明 // ... }; ``` 在`Singleton.cpp`中,我们实现`getInstance()`方法: ```cpp #include "Singleton.h" // 单例的静态成员变量,存储唯一实例 Singleton* Singleton::...

    singleton设计模式java实现及对比

    缺点:如果Singleton需要持有外部引用,可能会导致内存泄漏。 综上所述,Singleton模式的实现方式各有优劣,选择哪种方式取决于具体的应用场景和性能需求。在实际开发中,应根据项目需求选择最适合的Singleton实现...

    Singleton Pattern 源码

    单例模式(Singleton Pattern)是软件设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。这种模式在很多场景下非常有用,比如控制资源的唯一性、全局配置对象或者缓存服务等。本篇文章将深入探讨...

    Singleton 单例模式

    这种模式常用于系统资源管理,比如数据库连接、线程池或者缓存服务等,因为这些资源往往需要全局共享且控制其生命周期。 单例模式的核心思想在于控制类的构造函数,防止外部直接实例化。通常,我们会将构造函数设为...

    SingleTon的模板(template)化应用

    首先,我们需要理解单例模式的基本思想。单例模式通常包含两个关键点:一是控制类的实例化过程,只允许创建一个实例;二是提供一个全局访问点,使得任何地方都可以获取到这个唯一的实例。传统的C++单例实现可能使用...

    Java常用设计模式(SingleTon、FactoryMethod、AbstractFactory)

    Java设计模式是面向对象编程中的重要概念,它们是解决常见问题的经验总结,为代码的可重用性、可维护性和可扩展性提供了指导。这里我们将深入探讨三种常见的Java设计模式:单例(Singleton)、工厂方法(Factory ...

    linux 下线程安全的singleton

    singleton是最常见的设计模式,但是要设计好却是不容易,尤其是多线程的时候,需要考虑线程安全的问题.

    Java 单例模式Singleton

    简单的单例模式举例Singleton 分为恶汉式 懒汉式

    单例模式Singleton

    单例模式(Singleton Pattern)是一种常用的软件设计模式,它的核心思想是确保一个类在整个应用程序中只有一个实例存在,并提供一个全局访问点来获取这个实例。这种模式在很多场景下非常有用,比如管理系统资源、...

    SingletonTemplate

    在继承SingletonTemplate时,子类只需要关注自己的业务逻辑,无需关心单例的实现细节。这样的设计遵循了“开闭原则”,即对扩展开放,对修改关闭。 在实际编程中,需要注意单例模式的适用场景和潜在问题。虽然单例...

    (创建型模式)Singleton模式

    除了上述实现方式,还需要注意Singleton模式的一些扩展和讨论。例如,Singleton模式破坏了类的封装性,使得类的实例化过程不再由类自身控制,而是外部代码控制。这在某些情况下可能引发问题,比如测试和序列化。为了...

    Laravel开发-singleton-pattern

    Singleton确保一个类只有一个实例,并提供一个全局访问点,这样可以避免创建多个对象导致资源浪费,尤其适用于那些创建开销大或需要全局共享状态的类。 首先,我们要理解什么是单例模式。单例模式是一种创建型设计...

    单例极致 singleton C++

    1、没有构造函数(DEFINE_SINGLETON_DEFAULT); 2、有构造函数,构造函数没有参数(DEFINE_SINGLETON_CONSTRUCT_NO_PARAM); 3、有构造函数,构造函数有没有参数版本(DEFINE_SINGLETON_CONSTRUCT_WITH_DEFAULT)...

    Loki singleton

    然后,你可以为你的类定义一个Singleton模板实例,以确保该类在整个应用程序中只存在一个实例。以下是一个基本的示例: ```cpp #include &lt;Loki/Singleton.h&gt; class MyClass { public: // 确保你的构造函数是私有...

    单例模式Singleton(java源码)

    Singleton模式包含的角色只有一个,就是Singleton。Singleton拥有一个私有构造函数,确保用户无法通过new直接实例化它。除此之外,该模式中包含一个静态私有成员变量instance与静态公有方法Instance()。Instance()...

    单例实现源码singleton-C++

    以下是对"单例实现源码singleton-C++"的详细解析。 1. **静态成员变量法** 这是最常见的单例实现方式。在类中定义一个静态成员变量,该变量保存唯一的实例。例如: ```cpp class Singleton { public: static ...

Global site tag (gtag.js) - Google Analytics