A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

采用单例设计模式设计的类能完全阻止建立多个对象?

9 个回复

正序浏览
单例设计模式的思想就是  把构造函数私有化  使外界不能用该构造函数创建对象  并提供一个方法被外界调用来创建唯一对象
回复 使用道具 举报
如果是叫真,懒汉式如果不加锁,在遇到多线程的时候是可能出问题的,这个在教学视频时说的很清楚了。
就是在判断完if语句后,失去执行权,然后别的线程进入,由于前一个线程,只是判断完if语句,但是并没有生成对象,
所以第2个线程也可以通过if语句
回复 使用道具 举报
单例设计模式的思想就是  把构造函数私有化  使外界不能用该构造函数创建对象  并提供一个方法被外界调用来创建唯一对象  不能保证这一点  就不是单例设计模式了
回复 使用道具 举报
胥文 中级黑马 2013-2-27 22:28:47
7#
首先是不能阻止创建多个对象的
当反射出现的时候一切就变了
你可以通过反射来获取他私有的构造方法
然后再创建n个对象
eg:
class SingelDemo
{
        private SingelDemo(){}
        private static SingelDemo sd = new SingelDemo();
        public static SingelDemo getInstance()
        {
                return sd;
        }
        public void show()
        {
                System.out.println("hello");
        }
}

public class Test5 {

        public static void main(String[] args) throws SecurityException, Exception {
                //这是之前创建对象的方法
                SingelDemo sd1 = SingelDemo.getInstance();
                sd1.show();
               
                //通过反射获取构造函数,并创建多个对象
                Constructor constructor = SingelDemo.class.getDeclaredConstructor();
                constructor.setAccessible(true);
                SingelDemo sd2 = (SingelDemo) constructor.newInstance();
                SingelDemo sd3 = (SingelDemo) constructor.newInstance();
                SingelDemo sd4 = (SingelDemo) constructor.newInstance();
                SingelDemo sd5 = (SingelDemo) constructor.newInstance();
                System.out.println(sd2.equals(sd3));
                sd2.show();
                sd3.show();
               
               
               
        }

}
回复 使用道具 举报
Singleton模式的实现基于两个要点:
1)不直接用类的构造函数,而另外提供一个Public的静态方法来构造类的实例。通常这个方法取名为Instance。Public保证了它的全局可见性,静态方法保证了不会创建出多余的实例。
2)将类的构造函数设为Private,即将构造函数"隐藏"起来,任何企图使用构造函数创建实例的方法都将报错。这样就阻止了开发人员绕过上面的Instance方法直接创建类的实例。
通过以上两点就可以完全控制类的创建:无论有多少地方需要用到这个类,它们访问的都是类的唯一生成的那个实例。
回复 使用道具 举报
单例模式在不考虑序列化的情况下,无论勤加载还是懒加载,均是安全的.看你代码是怎么写的了.

但当单例执行了Serializiable接口以后,就不安全了. 将单例序列化再反序列化, 单例就多了一份copy.

但这个问题也不是不能解决,常用的方法有两种:

一. readResolve

public class Singleton implements Serializable {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
}
private Object readResolve() {
//readUnshared 返回该对象的浅表副本
return INSTANCE;
}
public static Singleton getInstance() {
return INSTANCE;
}
}

当进行反序列化时,  ois.readObject();时内部就是通过反射检查implements Serializable的类有没有

readResolve方法,如果有就把readResolve的返回值作为ois.readObject();的返回值. 所以readResolve必须返回之前对象的引用

二. 使用枚举式

使用了枚举特有的特性, 枚举序列化, 反序列化的对象然后是同一个对象. 可以自行查看ois.readObject();oos.writeObject(obj)代码, 它是

把枚举作为一种类型单独考虑的.
回复 使用道具 举报
如果还能创建 那还叫单例?
回复 使用道具 举报
class Demo11
{
        private static Demo11 d=new Demo11();
        private Demo11()
        {}
        public Demo11 getD()
        {
                return d;
        }
}//无论你怎么创建,反回的都是已经定义好的类对象d.
回复 使用道具 举报
构造方法私有化之后,外界就无法通过构造方法新建对象了
自己本类中建立自己的对象,然后对外提供一个方法,让外界获得对象
由于这个对象只能有这个类建立,所以可以实现单例
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马