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

 

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

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

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

但是不允许实例化,

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

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

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

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


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

而 类 不能。

 

 

 

分享到:
评论
26 楼 whaosoft 2009-06-07  
seraphim871211 写道
这帖子都有人投隐藏??

JE搞什么啊,投个良好冲下

其实我想给你良好 但我没那个能力
至于为什么都是单实例 我感觉不一定都是那样 你是不是看了 spring的配置的都是单实例呢
25 楼 seraphim871211 2009-06-07  
这帖子都有人投隐藏??

JE搞什么啊,投个良好冲下
24 楼 步行者 2009-06-07  
fjlyxx 写道
步行者 写道
fjlyxx 写道

将类定义为final吧

为什么要将类定义为 final 呢
即使被其他类继承 ,它的状态还是唯一的
它的子类可以使用父类的静态方法和静态属性
,却不会在内存中创造一份父类静态方法和静态
属性的的拷贝,
类的状态是唯一的,不能通过继承复制它,只能
通过特定接口访问它


呵呵,这是态度问题..其实没区别... 这个和写 class test和 class Test一样的道理. 规范.
一个是cannot subclass the final class
另一个是
Implicit super constructor   is not visible for default constructor. Must define an explicit constructor


呵呵 采纳意见。
不final 确实肯能会引起混淆,而且子类也可以实例化对象


23 楼 fjlyxx 2009-06-07  
步行者 写道
fjlyxx 写道

将类定义为final吧

为什么要将类定义为 final 呢
即使被其他类继承 ,它的状态还是唯一的
它的子类可以使用父类的静态方法和静态属性
,却不会在内存中创造一份父类静态方法和静态
属性的的拷贝,
类的状态是唯一的,不能通过继承复制它,只能
通过特定接口访问它


呵呵,这是态度问题..其实没区别... 这个和写 class test和 class Test一样的道理. 规范.
一个是cannot subclass the final class
另一个是
Implicit super constructor   is not visible for default constructor. Must define an explicit constructor
22 楼 步行者 2009-06-07  
dennis_zane 写道
楼主,你说的其实没问题,单例就是一个全局访问点,用全部是静态变量和静态方法的类来做同样可以。我看过这样的讨论,最后的结论是单例模式比之全静态类来说唯一的好处就是,你可以很容易将单例改成多实例,这个理由很薄弱。


支持这个观点,不过这个理由确实有点薄弱,呵呵
21 楼 步行者 2009-06-07  
qzzlw 写道
类的属性是全局的,系统一启动就已经在全局静态数据区分配好了资源,而单例是对象,只有在需要的时候才在堆内分配资源来放置实例属性。从封装的角度或者资源占用的角度来看 ,单例可能会更好一些。


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

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



20 楼 qzzlw 2009-06-07  
类的属性是全局的,系统一启动就已经在全局静态数据区分配好了资源,而单例是对象,只有在需要的时候才在堆内分配资源来放置实例属性。从封装的角度或者资源占用的角度来看 ,单例可能会更好一些。
19 楼 dennis_zane 2009-06-07  
楼主,你说的其实没问题,单例就是一个全局访问点,用全部是静态变量和静态方法的类来做同样可以。我看过这样的讨论,最后的结论是单例模式比之全静态类来说唯一的好处就是,你可以很容易将单例改成多实例,这个理由很薄弱。

18 楼 步行者 2009-06-07  
flyspider 写道
楼主的做法是单了,可惜没有"例"
静态属性和静态方法的做法不是说不可以达到目标,只是这样做初始化工作就交给了JVM,这样的做法基本丧失了主控性,也不利于测试,那么既然单例的做法更好,何乐不为呢?


如果对象不是单例,这种说法我就接受了
因为对象是单例,它的初始化实际上分为两步的:
    1,加载单例对应的类
    2,创建一个单例
而类也只会被加载一次,而且不一定非要在加载时 把所有的初始化工作都做了。
我们也可以在使用前做初始化工作。
所以我不觉得这是单例的优势!
17 楼 步行者 2009-06-07  
treenode 写道
如果单例对象需要 a. 从反序列化得来, b. 用Spring这样的框架装配而成,c. 根据实际的运行环境,向单例的构造函数传递不同的参数,那么使用类的静态成员就是不合适的。如果没有这些要求,以类为单例是足够了。



你的这三种情况 是针对对象的,因为类不是对象,确实不能满足。
不过类可以通过其他途径满足 这三种情况所要达到的目的。
a , 对象序列化 确实不保存 静态属性,但类的内部状态不是不可以保存并恢复的。
b , Spring 容器是管理对象的,当然不能管理类,类也不需要管理,因为它只有一个
索引它只需要类名就可以了。
c , 对象才有构造函数 ,类当然没有。但类可以使用静态初始化方法初始化类的内部状态。
16 楼 flyspider 2009-06-07  
楼主的做法是单了,可惜没有"例"
静态属性和静态方法的做法不是说不可以达到目标,只是这样做初始化工作就交给了JVM,这样的做法基本丧失了主控性,也不利于测试,那么既然单例的做法更好,何乐不为呢?
15 楼 night_stalker 2009-06-07  
步行者 写道
frenchmay 写道
确保当前虚拟机中只存在一份类的实例,为了在不同对象中安全地共享对象。
另外你写的这个单例的方法并非线程安全


线程安全很重要,但这不是讨论的重点
问题是 单例能线程安全 ,类也能线程安全啊。
为什么用单例 而 不用用静态属性和静态方法构造的类
来表达这种唯一性呢?


感觉不到好处就别用。不要成为 Stinkleton。
另外用 DI 就已经很方便了,现在手写 singleton 已经成为反模式了……
14 楼 步行者 2009-06-07  
frenchmay 写道
确保当前虚拟机中只存在一份类的实例,为了在不同对象中安全地共享对象。
另外你写的这个单例的方法并非线程安全


线程安全很重要,但这不是讨论的重点
问题是 单例能线程安全 ,类也能线程安全啊。
为什么用单例 而 不用用静态属性和静态方法构造的类
来表达这种唯一性呢?
13 楼 night_stalker 2009-06-07  
把构造函数私有化的那步放到最终具体类中,依然能用多态啊。


原型的对象系统就没这个问题,既然没有 class,就没有特意弄 singleton 的必要了。
引用
In a prototype-based programming language, where objects but not classes are used, a "singleton" simply refers to an object without copies or that is not used as the prototype for any other object. Example in Io:

Foo := Object clone
Foo clone := Foo
12 楼 步行者 2009-06-07  
fjlyxx 写道

将类定义为final吧

为什么要将类定义为 final 呢
即使被其他类继承 ,它的状态还是唯一的
它的子类可以使用父类的静态方法和静态属性
,却不会在内存中创造一份父类静态方法和静态
属性的的拷贝,
类的状态是唯一的,不能通过继承复制它,只能
通过特定接口访问它
11 楼 frenchmay 2009-06-07  
确保当前虚拟机中只存在一份类的实例,为了在不同对象中安全地共享对象。
另外你写的这个单例的方法并非线程安全
10 楼 treenode 2009-06-07  
如果单例对象需要 a. 从反序列化得来, b. 用Spring这样的框架装配而成,c. 根据实际的运行环境,向单例的构造函数传递不同的参数,那么使用类的静态成员就是不合适的。如果没有这些要求,以类为单例是足够了。

9 楼 ravenex 2009-06-07  
楼主问得好,这问题困惑小的多时,期待有大大完整解答一个
kaka11 写道
至于静态方法的话,是会限制了多态,所以很多情况在oo编程中它是不被用的,除非你确定你的类完全不需要,不可能使用到多态,比如像工具类,或者像active record里面的那些find方法,很多时候技术并没有对错,只是适合不适合和你是否需要一些oo的灵活性了。

常见的单例模式实现方法由于把构造器设为private,一样限制了多态,而且它的方法一般以实例方法为主,比静态方法慢。据说单例模式比静态类容易测试,因为有办法mock
8 楼 night_stalker 2009-06-07  
我觉得单例的原因是类型不能当对象用。
譬如函数传参数时你得传个对象或值,不能传类型。
所以把 static 的东西都改成非 static 的,强制只能实例化一遍,传递唯一的实例,就能模拟“传递类型”的效果了。另外 static 成员在继承的时候一坨乱糟糟也是个原因。
7 楼 rgrg 2009-06-07  
这样会损失面向对象的特性

相关推荐

Global site tag (gtag.js) - Google Analytics