`
步行者
  • 浏览: 169834 次
  • 性别: 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
	}
}

 

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

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

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

但是不允许实例化,

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

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

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

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


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

而 类 不能。

 

 

 

分享到:
评论
106 楼 徐风子 2009-09-03  
以前喜欢用静态类,不过现在较多用单例了。

首先从定义上说,静态类是违反面向对象原则的(书上看的,至于有什么问题暂时还没想清楚 ^_^),面向对象的原则是任何事物皆属于对象,静态类属于哪一个对象?

单例操作起来是很方便,
像接口,比如A、B 两个单例,同实现一个接口I,我可以在参数类型I中任选一个传递,这是静态类无法实现的。

还有代理,如果我要给一个单例的所有方法加一个缓存代理(实际应用中一种很常见的优化技术,缓存代理肯定是公共方法)。静态类就无法实现。

当然上面这些你可以用其他方法实现,但毕竟很麻烦,设计不就是为了简单易读吗。

如果你暂时不需要这些功能,也不能保证以后不会扩展到这个功能,所以…… 用单例吧。

哦,只私有化构造函数是无法保证单例的,因为有反射,要在构造方法里面加上throw才行。
105 楼 solonote 2009-09-02  
Singleton 模式随着容器的出现,也渐渐走出历史舞台了
104 楼 MVC2008MVC 2009-08-19  
静态类的方法只能调用静态的。而非静态的方法都可以调用的。
103 楼 javatestoracle 2009-08-17  
我认为要不要单例有以下几个因素决定的

    1: 这个类的实例是不是要频繁的被使用,并且里面成员变量是不会改变,或者很少改变的
        如果要遇到以上情况,使用单例是个不错的选择

    2: 第二 ,这个类,是不是会参与到多态中来, 如果要参与多态,那么就要放弃单例的写法

   
102 楼 michael.softtech 2009-07-31  
谨慎发表一下我的观点:

使用对象的情况:
   如果不用单例,那么他就是一个普通对象,不排除有人获取另一个对象,那么如果这个单例是有状态的,并且需要保持这个状态的唯一性,那么多个对象就会出现问题


使用静态类情况:
   类中静态变量是以开始就加载的,而单例是需要时分配堆。如果系统中有很多地方可能需要单例,那么应用一启动就加载这些类,会不会影响性能哪?
101 楼 mark_wang_9527 2009-07-31  
<div class="quote_title">ninini 写道</div>
<div class="quote_div">
<div class="quote_title">wy19280469 写道</div>
<div class="quote_div">
<br>对象创建也需要加载类啊  --&gt; 不是同一个内存空间  而static 只创建一个内存空间   对象创建是new 的过程<br>static 不用吧。<br><br>static 也支持并发啊  --&gt; 如果定义static 属性的话  怎样保证并发的安全性? 同一个地址 你调用时一个值 如果你改变了这个值的时候 ,那下一个人调用的时候 还以为是原来的值怎么办?<br><br>
</div>
<p> </p>
<p>??? </p>
<p>创建一了类的对象首先要加载相应类,当然只需要加载一次</p>
<p>static 可以保持线程同步,跟非static是一个道理啊</p>
<p> </p>
</div>
<p>现在不是多核处理器了么,Static应该不像提倡Moore的单核时代了,Singleton,Static不向以前那么安全了,单核时候可以是同步,毕竟CPU只能在同一时间处理同一任务,多核的话就能同时处理CPU数量的任务,.NET里面都有控制各处理器处理指定线程的基础库,JAVA里面应该也有吧(暂时没找到)</p>
100 楼 mark_wang_9527 2009-07-30  
<div class="quote_title">步行者 写道</div>
<div class="quote_div">
<p><span style="font-size: small;">为什么需要 单例设计模式(Singleton)?</span> </p>
<p><span style="font-size: small;">像下面的一个单例</span> </p>
<p> </p>
<pre name="code" class="java">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
}
}</pre>
<p><span style="font-size: small;"><br></span></p>
<p><span style="font-size: small;">它要实现的主要目标,就是在一个应用中只维护一个Singleton实例 </span></p>
<p><span style="font-size: small;">但一个类在一个应用中也是唯一的,为什么不能直接以类作为单例呢?</span> </p>
<p> </p>
<pre name="code" class="java">public final class AnotherSingleton{
private AnotherSingleton(){}
public static synchronized void doSomething(){
//do something
}
}</pre>
<p> </p>
<p><span style="font-size: small;">把类的所有方法都改为静态方法,</span> </p>
<p><span style="font-size: small;">所有属性都改为静态属性(我们可以把</span> </p>
<p><span style="font-size: small;">静态属性看成类的内部状态),</span> </p>
<p><span style="font-size: small;">但是不允许实例化,</span> </p>
<p><span style="font-size: small;">对类的操作相当于对单例的操作</span> </p>
<p><span style="font-size: small;">而且类也可以维护内部状态(通过静态私有属性)</span> </p>
<p><span style="font-size: small;">这完全满足了单例的要求。</span> </p>
<p><span style="font-size: small;">不知道为什么需要单例模式。。。</span> </p>
<p><span style="font-size: small;"><br></span></p>
<p><span style="font-size: small;">因为我想不出来在什么情况下 单例可以满足需求</span> </p>
<p><span style="font-size: small;">而 类 不能。</span> </p>
<p> </p>
<p>面向对象原则,违背封装跟多态,静态本来就违背面向对象原则,即为面向过程,正如楼上说的不如写C</p>
<p>PS:楼主这代码也不算是一个绝对的单例,1.采用反射机制可以创建多个实例 2.未重写readReslove方法,反序列化产生2个实例 3.建议用枚举来做单例以上两种问题均已解决 4.同步方法改为Volatile跟块双重锁更佳</p>
<p> </p>
<p> </p>
<p> </p>
</div>
<p> </p>
99 楼 ninini 2009-06-14  
<div class="quote_title">wy19280469 写道</div>
<div class="quote_div">
<br>对象创建也需要加载类啊  --&gt; 不是同一个内存空间  而static 只创建一个内存空间   对象创建是new 的过程<br>static 不用吧。<br><br>static 也支持并发啊  --&gt; 如果定义static 属性的话  怎样保证并发的安全性? 同一个地址 你调用时一个值 如果你改变了这个值的时候 ,那下一个人调用的时候 还以为是原来的值怎么办?<br><br>
</div>
<p> </p>
<p>??? </p>
<p>创建一了类的对象首先要加载相应类,当然只需要加载一次</p>
<p>static 可以保持线程同步,跟非static是一个道理啊</p>
<p> </p>
98 楼 wy19280469 2009-06-14  
ninini 写道
wy19280469 写道
如果什么都定义STATIC
那在类加载的时候 内存得被占用多少呢?
如果属性被定义成STATIC
那在发生并发的时候如何避免数据准确呢?
如果类都定义成STATIC
那这个类如何重用呢?意思是说这个类同时被多个调用

我只有在数据唯一确定不变的情况下 来做STATIC 例如数据库连接

其他的要视情况而定~

例如管理Hibernate的Session 就会用到ThreadLocal 也会被定义成Static 因为就需要使用一个。

我怎么感觉你说的都不对啊???
? 1,对象创建也需要加载类啊
? 2,static也支持并发啊
? 3,类可以同时被多个调用啊



对象创建也需要加载类啊  --> 不是同一个内存空间  而static 只创建一个内存空间   对象创建是new 的过程
static 不用吧。

static 也支持并发啊  --> 如果定义static 属性的话  怎样保证并发的安全性? 同一个地址 你调用时一个值 如果你改变了这个值的时候 ,那下一个人调用的时候 还以为是原来的值怎么办?

97 楼 ninini 2009-06-14  
wy19280469 写道
如果什么都定义STATIC
那在类加载的时候 内存得被占用多少呢?
如果属性被定义成STATIC
那在发生并发的时候如何避免数据准确呢?
如果类都定义成STATIC
那这个类如何重用呢?意思是说这个类同时被多个调用

我只有在数据唯一确定不变的情况下 来做STATIC 例如数据库连接

其他的要视情况而定~

例如管理Hibernate的Session 就会用到ThreadLocal 也会被定义成Static 因为就需要使用一个。

我怎么感觉你说的都不对啊???
? 1,对象创建也需要加载类啊
? 2,static也支持并发啊
? 3,类可以同时被多个调用啊
96 楼 wy19280469 2009-06-14  
如果什么都定义STATIC
那在类加载的时候 内存得被占用多少呢?
如果属性被定义成STATIC
那在发生并发的时候如何避免数据准确呢?
如果类都定义成STATIC
那这个类如何重用呢?意思是说这个类同时被多个调用

我只有在数据唯一确定不变的情况下 来做STATIC 例如数据库连接

其他的要视情况而定~~~

例如管理Hibernate的Session 就会用到ThreadLocal 也会被定义成Static 因为就需要使用一个。
95 楼 步行者 2009-06-13  
fjlyxx 写道
唉,讨论了这么多.单例的实现已经很完美了,不需要再多的优化了,但是这种单例只限于同一个jvm 如果我是一个分布式系统 或者不同JVM LZ你又打算如何实现呢?


分布式系统 共享一个单例,
如果以对象方式实现 这种单例的 一致性,应该是当
分布式系统中的一个节点 的单例 发生状态改变时,
更新所有节点相应单例的状态,可能一种实现方案就是
通过对象 序列化
虽然类不能 序列化,但它的 静态属性 是可以存储并恢复的,
这也可以解决 AnotherSingleton 在分布式系统下的一致性问题。


94 楼 fjlyxx 2009-06-13  
唉,讨论了这么多.单例的实现已经很完美了,不需要再多的优化了,但是这种单例只限于同一个jvm 如果我是一个分布式系统 或者不同JVM LZ你又打算如何实现呢?
93 楼 jansel 2009-06-12  
两种单例的实现而已,都是单例。如果从单例看的话,两者没有区别。
92 楼 步行者 2009-06-12  
幸存者 写道
一些显而易见的好处是Singleton可以赋值,可以当成参数或返回值传来传去,多个Singleton可以共同实现某个接口而实现多态。

“可以当成参数或返回值传来传去”
这是对象的好处 ,但如果对象是单例,就另当别论了!
不过我们引用Singleton的时候,
好像大多是以这种方式
Singleton singleton = Singleton.getInstance();
那么既然 通过 这种方式就可以引用到 单例
我们 还需要把它作为输入输出,
在方法中作为参数进行引用吗,
单例 只有一个,
所以把它作为参数 和 像上面的方式写在方法里 来获取Singleton,
应该没有区别
那么 何必 把Singleton写在参数列表里呢,因为怎么传都只有它一个

但如果多个Singleton共同实现了某个接口而实现多态。
那么 作为参数或返回值传来传去 就变得有意义了
是一个优势 !!!
不过感觉有点弱(多个Singleton共同实现了某个接口)
91 楼 幸存者 2009-06-11  
一些显而易见的好处是Singleton可以赋值,可以当成参数或返回值传来传去,多个Singleton可以共同实现某个接口而实现多态。
90 楼 步行者 2009-06-11  
qzzlw 写道

类是什么呢?类只不过是方法和数据的集合,方法都在代码段,这部分内存是不可能省掉的。数据如果是静态的,就在全局数据段,这部分永远会加载到内存。实例数据只有在构造类实例的时候才占有堆内存。



我承认 “数据如果是静态的,就在全局数据段”
这部分在类被加载时才会被加载到内存
89 楼 qzzlw 2009-06-11  
步行者 写道
qzzlw 写道
步行者 写道
qzzlw 写道
类的属性是全局的,系统一启动就已经在全局静态数据区分配好了资源,而单例是对象,只有在需要的时候才在堆内分配资源来放置实例属性。从封装的角度或者资源占用的角度来看 ,单例可能会更好一些。


类不是在系统一启动时就加载,而是在第一次引用,或实例化时进行加载
还有另一种方法加载类
Class.forName("XXX");
反而对象的初始化要先加载类,
再进行实例化。
所以我觉得从资源占用的角度来看 ,类反而要好一些。

至于封装,也可以通过私有静态属性来封装类状态,
我觉得这也不是问题




我说的是属性,不是类加载的问题。静态的属性肯定是放在全局数据段,而且一直占用,实例属性是在堆中需要的时候分配的。我这是从PE文件结构来理解的,java虚拟机应该也差不多。


静态属性也是在需要的时候被加载进内存的啊 
静态属性不是定义在类中吗
类加载后 类的属性才能被放在全局数据段中

实例属性 也只有实例被创建后才能被保存到堆中
但首先也需要加载相应的类



类是什么呢?类只不过是方法和数据的集合,方法都在代码段,这部分内存是不可能省掉的。数据如果是静态的,就在全局数据段,这部分永远会加载到内存。实例数据只有在构造类实例的时候才占有堆内存。
88 楼 步行者 2009-06-11  
qzzlw 写道
步行者 写道
qzzlw 写道
类的属性是全局的,系统一启动就已经在全局静态数据区分配好了资源,而单例是对象,只有在需要的时候才在堆内分配资源来放置实例属性。从封装的角度或者资源占用的角度来看 ,单例可能会更好一些。


类不是在系统一启动时就加载,而是在第一次引用,或实例化时进行加载
还有另一种方法加载类
Class.forName("XXX");
反而对象的初始化要先加载类,
再进行实例化。
所以我觉得从资源占用的角度来看 ,类反而要好一些。

至于封装,也可以通过私有静态属性来封装类状态,
我觉得这也不是问题




我说的是属性,不是类加载的问题。静态的属性肯定是放在全局数据段,而且一直占用,实例属性是在堆中需要的时候分配的。我这是从PE文件结构来理解的,java虚拟机应该也差不多。


静态属性也是在需要的时候被加载进内存的啊 
静态属性不是定义在类中吗
类加载后 类的属性才能被放在全局数据段中

实例属性 也只有实例被创建后才能被保存到堆中
但首先也需要加载相应的类


87 楼 qzzlw 2009-06-11  
步行者 写道
qzzlw 写道
类的属性是全局的,系统一启动就已经在全局静态数据区分配好了资源,而单例是对象,只有在需要的时候才在堆内分配资源来放置实例属性。从封装的角度或者资源占用的角度来看 ,单例可能会更好一些。


类不是在系统一启动时就加载,而是在第一次引用,或实例化时进行加载
还有另一种方法加载类
Class.forName("XXX");
反而对象的初始化要先加载类,
再进行实例化。
所以我觉得从资源占用的角度来看 ,类反而要好一些。

至于封装,也可以通过私有静态属性来封装类状态,
我觉得这也不是问题




我说的是属性,不是类加载的问题。静态的属性肯定是放在全局数据段,而且一直占用,实例属性是在堆中需要的时候分配的。我这是从PE文件结构来理解的,java虚拟机应该也差不多。

相关推荐

    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