黑马程序员技术交流社区
标题:
单例设计模式思想问题
[打印本页]
作者:
尹善波
时间:
2012-7-30 01:07
标题:
单例设计模式思想问题
//单例设计模式
class Single
{
private int num;
public void setNum(int num)
{
this.num=num;
}
public int getNum()
{
return num;
}
private Single
(){}//构造这个空的构造函数有具体的用途吗,有的话是什么?
private static Single s = new Single
();//创建这个本类对象难道就能禁止其他程序创建该类对象吗;
//有什么用途?
public static Single getInstance()
{
return s;
}
}
class SingleDemo
{
public static void main(String[] args)
{
Single s1 = Single.getInstance();
Single s2 = Single.getInstance();
s1.setNum(23);
System.out.println(s2.getNum
());//为什么s2调用getName方法会返回s1设置的值,
//请详细说明,要是有具体步骤更好
}
}
/*
单例设计模式的总体思想是什么,能不能用好理解的话说说?
单例设计模式能保证对象的唯一,但是什么情况下才会运用到呢
*/
作者:
李菁
时间:
2012-7-30 01:26
构造函数私有化是为了不让别的类随便new这个类。
在本类中,new自己的静态对象,通过一个公有的方法返回这个对象。这样就形成了单例设计模式
只需要使用一个单独的资源,并且需要共享这个单独资源的状态信息时,就能用到单例模式。
单例最具体的一个例子就是播放器,不能同时听两个界面的歌曲,当播放时再想打开另一个时,当前窗口关闭。
作者:
陈汉维
时间:
2012-7-30 01:30
本帖最后由 陈汉维 于 2012-7-30 01:35 编辑
private Single(){}//构造这个空的构造函数有具体的用途吗,有的话是什么?
该空的构造函数式私有的,为了不允许其他程序用new创建该类对象。
private static Single s = new Single();//创建这个本类对象难道就能禁止其他程序创建该类对象吗;//有什么用途?
用途是:在该类创建一个本类实例
public static Single getInstance()
{
return s;
}这个用于对外提供一个方法让其他程序可以获取该对象
System.out.println(s2.getNum());//为什么s2调用getName方法会返回s1设置的值
因为Single s1 = Single.getInstance();和Single s2 = Single.getInstance();都必须通过Single里面的getInstance()方法获取已创建的对象,
也就是说对象s1和s2是相等的,他们有一样的内存地址。所以System.out.println(s2.getNum());返回的是同一个内存地址里面的值
单例设计模式:就是为了保证一个类在内存中的对象唯一性。
比如window下的回收站,它是唯一的,运用的就是单例设计模式。你手动点开回收站,然后最小化,然后在点开一个新的回收站,最小化的那个回收站就会展开,不能同时打开2个回收站,这就是单例设计模式。
作者:
fiend
时间:
2012-7-30 01:47
private Single(){}//构造这个空的构造函数有具体的用途吗,有的话是什么?
答:构造函数当然是构造对象用的。当你实例化一个对象的时候就会调用构造函数。之所以是private的,就为了只能类内部调用,也就是只能在这个类的内部构造对象。
private static Single s = new Single();//创建这个本类对象难道就能禁止其他程序创建该类对象吗;
//有什么用途?
答:访问控制符为private就是为了不让别人直接调用,只能内部调用。定义为static的就是为了只产生一个对象,因为static的在加载类的时候就会实例化。以后用就是了,不会再产生新的对象。
System.out.println(s2.getNum());//为什么s2调用getName方法会返回s1设置的值,
//请详细说明,要是有具体步骤更好
答:单例单例,顾名思义,只会有一个对象,所以s1和s2指向的是同一个对象,那操作s1和操作s2也是在操作同一个对象,所以返回值是s1设置的。s1和s2相当于两个遥控器,但是它们遥控的是同一台电视机。
至于什么时候能用到,比如你做一个五子棋游戏,那些棋子都是一样的,如果每一个你都new一个对象的话,就太多对象了,太难管理,影响效率,这时就可以用单例来解决,也就是传说中的享元模式。
作者:
肖琦
时间:
2012-7-30 07:38
以上单例的思想说得都很好,我就补充点吧!
创建单例通常分两种方式:
饿汉模式:
class Single{
private Single{}
private static Single instance = new Single();//对象直接实例化
public static Single getInstance(){
return instance;
}
}
懒汉模式(非终极版):
class Single{
private Single{}
private static Single instance = null;//对象先不实例化
public static Single getInstance(){
if(instance == null)
instance = new Single();//实例在此处加载
return instance;
}
}
两种都是创建单例,普通情况下没什么区别,但在碰到多线程问题时,懒汉模式就会碰到问题。因为懒汉模式的特点就是 实例的延迟加载,有可能两个线程同时判断了满足了为null的条件,第一个还没实例化等着,第二个就实例了,接着第一个就不需要判断又实例化一遍,创造的实例就不是一个了,有违单例思想。为了处理这种问题,就只有给懒汉模式的单例加锁,如下(并非最终版):
public static synchronized Single getInstance(){//通过synchronized给加锁
if(instance == null)
instance = new Single();
return instance;
}
加完锁后,又会碰到一个问题,就是每次调用时都会判断是否有锁,这样效率很低。因此接着改进:
public static Single getInstance(){
if(instance == null){
synchronized(Single.class){
if(instance == null)
instance = new Single();
}
}
return instance;
}
这样就解决了效率的问题,只是多个线程加载单例的实例时才会上锁,只要有一个实例加载完了,之后的线程就不用判断锁了。(给人感觉是,懒汉虽懒,考虑的问题还是挺多的。建议开发中用饿汉模式)。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2