黑马程序员技术交流社区

标题: 什么是单列设计模式? [打印本页]

作者: 杨银川    时间: 2011-12-3 18:09
标题: 什么是单列设计模式?
本帖最后由 杨银川 于 2011-12-3 19:06 编辑

什么是单列设计模式?谁可以解释一下啊,谢谢
作者: 李晓斌    时间: 2011-12-3 18:14
单例模式:解决一个类在内存中只存在一个对象。
想要保证对象唯一:
为了避免其他程序过多建立该类对象。先禁止其他程序建立该类对象。
还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。
为了方便其他程序对自定义对象的访问,可以对外提供访问方式。
饿汉式:class Single
{
        private Single(){}
        private static Single s =new Single();
        public static Single getInstance()
        {
        return s;
        }
}
懒汉式:
class Single
{
        private static Single s=null;
        private Single(){}
        public static Single getInstance()
        {
        if (s==null)
        s= new Single();
        return s;
        }
}
两者区别:饿汉式先出示换对象。懒汉式方法被调用时,才初始化,也叫做对象的延时加载。但是,开发一般用饿汉式。
这都是视频上老毕说的
作者: 段波    时间: 2011-12-3 18:29
      单例设计模式是24种设计模式中用得还是比较多的一种设计模式吧!非常有用,一定要掌握哦!
单例就是某个类只允许有一个实例对象的存在,写单例要注意几点规则:
    1.构造函数为private
      2.有一个static的private的该类变量,在类初始化时实例化
    3.一个public的getInstance方法获取对它的引用,继而调用其中的方法
文字太抽象,还是代码清楚点吧,写单例有三种方法:

    第一种:饱汉模式
public class SingleTon {
        private SingleTon(){
                }       
        private final static SingleTon instance = new SingleTon();
        public static SingleTon getInstance(){
                return instance;
        }
}
第二种:饥汉模式
public class SingleTon {
        private SingleTon(){}
       
        private static instance = null;
       
        public static synchronized SingleTon getInstance(){
                if(instance == null)
                        instance = new SingleTon();
                return instance;
        }
}
第三种:用枚举,这是java5中的新特性哦!
        public enum SingleTon{
                ONE;
        }
不知道你对单例设计模式有没有一个深入的了解了!

作者: 许邦存    时间: 2011-12-3 18:30
恩,单态设计模式就是该类只能有一个对象,保证对象的唯一性,老毕的视频有讲到懒汉和饿汉,区别如楼上所说,建议楼主看下老毕的视频就理解了。
作者: 刘海涛    时间: 2011-12-3 21:24
首先从语义上理解什么是单列模式:单列模式即在应用中该类只允许创建一个实例(实例就有通过new才可以创建),
下面解决在应用一个类只允许创建一个实例:
        1、一般情况我们的类有默认的空的构造方法,但是如果不加以限制没办法达到目的,很容易想到修饰符,private (具体的我不做多的解释),可以保证除了本类其他地方都没法new ;
            例如:Student类 有个 private Student(){}
        2、 解决给外部提供一个可以获取本类实例的方法. 不new对象可以访问的可以是static 修饰的方法或者成员变量。考虑类的封装性,我们优先考虑用方法。
            例如:public static Student getInstance() {
                return new Student();
            }
        3、上面第二步我们可以多次调用,还是会创建实例,我们需返回的对象是只new .如果我们将实例保存起来,每次调用只是返回一个值。而我们如果保证保存的值只new 一次呢。
           我们可以是保存的值是静态的。因为静态成员变量初始化值只会被调用一次。
           例如: private static Student student = new Student();
                 private Student(){}
                 public static Student getInstance() {
                        return student;
                 }
这样我们基本实现在应用一个类只允许创建一个实例。

但是我们在应用中可能会存在一些问题。看下面例子:

        class A {
            private Student1 student1 = null;
            private Student2 student2 = null;
            private Student3 student3 = null;
            ..................
         
        }
当A类有100000个这样的成员变量单例的对象引用。在new A()时候就会创建100000个实例student1 student2......,因为只要用到了类的就会初始化该类的静态资源。
这样会导致系统浪费资源。为了解决这个问题我们需要着手如果在用到的时候才去创建引用的实例。
代码如下:
private static Student student = null;
private Student(){}
public static synchronized  Student getInstance() {
        if (student == null) {
                 student = new Student();
        }
        return student;
}

这样才可以在使用的时候才去new (术语:延迟加载,单例中称为饥汉模式)

关于public static synchronized  Student getInstance()中的synchronized,为了在多线程的情况下,可能会两个线程同时进入if (student == null) {这行代码,这样就会创建2个实例,加上synchronized就不会出现这样的情况。但是我们加上synchronized 会给getInstance()这个方法性能带来下降。下面是改造下上面的代码:

private ReadWriteLock lock = new ReentrantReadWriteLock();
private static Student student = null;
private Student(){}
public static  Student getInstance() {
        lock.readLock().lock();
                if (student == null) {
                        lock.readLock().unlock();
                        lock.writeLock().lock();
                        if (student == null) {
                                student = new Student();
                        }
                        lock.readLock().lock();
                        lock.writeLock().unlock();
                }
                lock.readLock().unlock();
        return student;
}

这样来可以实现读的时候不同步,可以同时读,当为空的时候同步写入。(上面的ReadWriteLock需要了解下java.util.concurrent包下面的一些类。)


另外 java 5 中的枚举类也是一种特殊的单例


单例的实现的方式各有各的好处,应当选择自己最合适的方式。

写得比较零散,如果有不懂的地方请留言。
作者: 杨银川    时间: 2011-12-3 21:44
恩,太谢谢大家了




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2