论单例的写法

简介: 有一回对我说道,“你学过设计模式么?”我略略点一点头。他说,“学过,……我便考你一考.设计模式的单例,怎样写的?”我想,讨饭一样的人,也配考我么?便回过脸去,不再理会.孔乙己等了许久,很恳切的说道,“不能写罢?……我教给你,记着!这些模式应该记着.将来当面试官的时候,面试要用.”我暗想我和面试官的等级还很远呢又好笑,又不耐烦,懒懒的答他道,“谁要你教?”孔乙己显出极高兴的样子,将两个指头的长指甲敲着柜台,点头说,“单例有六种写法,你知道么?

单例模式,顾名思义,就是全局只保存有一个实例并且能够避免用户去手动实例化,所以单例模式的各种写法都有一个共同点,不能通过new关键字去创建对象,因此,如果能够通过构造方法实例化,那么就一定要将其声明为私有。

饿汉式

public class PersonResource {
    public static final PersonResource PERSON_RESOURCE_SINGLETON = new PersonResource();
    private PersonResource(){}
    public  static PersonResource getInstance() {
        return PERSON_RESOURCE_SINGLETON;
    }
}

这种方式可以说是最安全,也最简单的了,但却有一个缺点,那就是无论这个实例有没有被使用到,都会被实例化,颇有些浪费资源

懒汉式一

既然前一种方法有些浪费资源,那就换一种写法,让类在被调用的时候实例化

public class PersonResource {
    private static PersonResource personResourceSingleton;
    private PersonResource() {

    }
    public static PersonResource getPersonResourceSingleton(){
        if(null==personResourceSingleton){
            personResourceSingleton = new PersonResource();
        }
        return personResourceSingleton;
    }
}

这种方式能够在需要用到该实例的时候再初始化,也能够在单线程下很好的运行,但如果是多线程就容易出现问题了。

懒汉式二

public class PersonResource {
    private static PersonResource personResourceSingleton;
    private PersonResource() {

    }
    public synchronized static PersonResource getPersonResourceSingleton(){
        if(null==personResourceSingleton){
            personResourceSingleton = new PersonResource();
        }
        return personResourceSingleton;
    }
}

多线程之所以会出现问题,是因为多个线程能够并发执行getPersonResourceSingleton方法,从而导致在判断是否为空时出现问题。

既然如此,加上锁 ,使其互斥即可。这里又出现了一个问题,每次获取实例的时候都需要加锁解锁,而当一个实例已经被产生后,再加锁就有些多余了;

懒汉式三(双重检查)

public class PersonResource {
    private PersonResource(){    }
    private volatile static PersonResource personResource;
    public  static PersonResource getInstance(){
        if(personResource==null){
            synchronized (PersonResource.class){
                if(personResource==null){
                    personResource = new PersonResource();
                }
            }
        }
        return personResource;
    }
}

既然实例确定产生后不再需要加锁,那我们在获取锁前先判断一次是否已经有实例存在就可以解决问题了

静态内部类

public class PersonResource {
    private PersonResource(){}
    private static class PersonResourceHolder{
        public static PersonResource personResourceSingleton = new PersonResource();
    }
    public static PersonResource getInstance(){
        return PersonResourceHolder.personResourceSingleton;
    }
}

除了双重检查能够保证安全的单例外,用一个静态内部类去持有单例也是可以的,静态内部类保证了不会随外部类的加载而加载,这保证了延迟加载,同时在加载该类的时候就实例化单例,保证了线程安全;

枚举

public enum PersonResource {
    /**
     * PersonResource单例
     */
    personResource;
    public void setPersonResource(){

    }
}

以上几种方式基本就够用了,但都有一个共同的缺点,面对序列化和反序列化,是无法保证单例的,但枚举的特性却能保证这一点

目录
相关文章
|
1月前
|
设计模式 存储 Java
JavaSE——面向对象高级一(2/4)-饿汉式单例、懒汉式单例、代码块、static的注意事项
JavaSE——面向对象高级一(2/4)-饿汉式单例、懒汉式单例、代码块、static的注意事项
17 0
|
12月前
|
安全
单例模式的写法
单例模式的写法
|
安全 Java
单例模式的8种写法
单例模式的8种写法
单例模式的8种写法
|
SQL 设计模式 安全
6. 单例模式有几种写法?
6. 单例模式有几种写法?
89 0
6. 单例模式有几种写法?
构造函数创建对象案例
构造函数创建对象案例
43 0
|
SQL 设计模式 安全
|
设计模式 安全 Java
单例模式的七种写法,你都知道吗?
单例模式的七种写法,你都知道吗?
177 0
单例模式的七种写法,你都知道吗?
|
设计模式 安全 算法
Java单例模式的不同写法(懒汉式、饿汉式、双检锁、静态内部类、枚举)
Java单例模式的不同写法(懒汉式、饿汉式、双检锁、静态内部类、枚举)
143 0
|
安全 Java
单例模式的N种写法
1.前言 写完这个题目,我感觉自己好像"孔乙己"啊,回字的四种写法要不要学啊~ 我们经常会用到单例模式,但是我对他一直没有一个统一的的认识,比如我清楚好多种单例的写法,但是每一种是怎么演化来的?具体解决了什么问题?这块就没有那么清晰了,因此此文对单例模式进行一个总结,同时手撸一下代码加深理解.
1251 0
|
安全 Java Android开发