设计模式-单例模式及使用场景

我们要明白why?为什么要用单例? where?单例用在什么地方?这个问题请在文末寻找。先看怎么来写单例。

特点

单例类只能有一个实例
单例类必须自己创建自己的唯一实例
单例类必须给所有其他对象提供这一实例

写法

/**
 * 懒汉式单例
 * @author qian.cheng
 *
 */
public class SingletonHungry {
    //私有无参构造方法,保证除此类外通过实例化无法获取实例
    private SingletonHungry(){}
    //需要时再新建实例
    private static SingletonHungry singletonHungry;
    //返回该单例实例
    public static synchronized SingletonHungry getInstance() {
        if(singletonHungry==null) {
            singletonHungry=new SingletonHungry();
        }
        return singletonHungry;
    }
}

/**
 * 饿汉式单例
 * @author qian.cheng
 *
 */
public class SingletonLazy {
    //私有无参构造方法,保证除此类外通过实例化无法获取实例
    private SingletonLazy(){}
    //在程序启动时就初始化,一直存在内存中
    private static final SingletonLazy SINGLETON_LAZY=new SingletonLazy();
    //返回该单例实例
    public static synchronized SingletonLazy getInstance() {
        return SINGLETON_LAZY;
    }
}

为什么叫饿汉懒汉呢?

饿汉式每次调用的时候不用做创建,直接返回已经创建好的实例。这样虽然节省了时间,但是却占用了空间
懒汉式第一次调用创建,以后之后返回第一次创建的实例,在一次创建的时候会慢一些。节省了空间,占用了时间

那么为什么我们要使用单例模式呢?

原因1:
因为我们知道内存分为堆内存和栈内存,A a=new A();栈内存里的是A对象的索引变量a,而a变量持有的A对象在堆内存。如果a一直持有对象A的引用,导致GC无法回收,就会引起内存泄漏,而我们上文提到的单例模式的特点完美解决了这一点。
原因2:
如果我们操作非单例模式的属性时,可能会出现数据错乱,举个栗子。

public class SingletonTest {
    static class A{
        int i=0;
    }
    public static void main(String[] args) {
        A a1=new A();
        a1.i++;
        A a2=new A();
        System.out.println(a2.i);
    }
}

打印结果为0,为什么呢,我是把A的i加1,之后再打印就变成0了?because 我们操作的是a1对象的i属性,而我们打印的是a2对象的i值。

public class SingletonTest {
    static class A{
        int i=0;
    }
    public static void main(String[] args) {
        A a1=new A();
        a1.i++;
        A a2=new A();
        System.out.println(a1.i);
    }
}

我们打印一下a1的值,是1.

什么地方调用单例模式呢?

像windows系统的回收站,手机和电脑的文件管理系统,同一时刻只能有一个访问,而且只允许存在一个对象。还有安卓的全局Context等等

猜你喜欢

转载自blog.csdn.net/ch1406285246/article/details/78657595