java23种设计模式(三)单例模式

原文地址:https://zhuanlan.zhihu.com/p/...html

1、概述

一、什么是单例模式?java

百度百科是这样定义的:单例模式是一种经常使用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。经过单例模式能够保证系统中一个类只有一个实例设计模式

我是这样理解的:单例模式就是只容许一个实例,最开始使用它的时候是C#中,我要实例化一个A窗体,可是有个需求就是A窗体必须是惟一,无论我在B窗体操做A窗体仍是C窗体中操做A窗体都是如此,这时候就使用到了单例模式安全

二、单例模式分类并发

A、懒汉单例模式:在第一次调用的时候实例化自己,在并发环境下,可能出现多个自己对象。因此线程是不安全的函数

B、饿汉单例模式:在类初始化时,已经自行实例化一个静态对象,因此自己就是线程安全的性能

C、登记单例模式:经过一个专门的类对各单例模式的单一实例进行管理和维护学习

三、特色编码

A、 单例模式类只能有一个实例
B、 单例模式类必须本身建立本身的惟一实例
C、 单例模式类必须给全部其余对象提供这一实例.net

2、运用

一、懒汉单例模式

/**
 * 描述:懒汉单例模式<p>
 * 做者: kimball <p>
 * E-mail: kimballlu@foxmail.com <p>
 * 日期:2016-11-16 下午4:30:32 <p>
 */
public class Singleton {
    
    /**
     * 该函数限制用户主动建立实例
     */
    private Singleton() {}
    private static Singleton singleton = null;
    
    /**
     * 获取Singleton实例(也叫静态工厂方法)
     * @return Singleton
     */
    public static Singleton getSingleton() {
        /* 当singleton为空时建立它,反之直接返回,保证惟一性 */
        if(singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
    
}

线程安全的懒汉单例模式

在getSingleton()添加synchronized同步

/**
 * 描述:懒汉单例模式,在getSingleton()方法添加同步<p>
 * 做者: kimball <p>
 * E-mail: kimballlu@foxmail.com <p>
 * 日期:2016-11-16 下午4:30:32 <p>
 */
public class Singleton {
    
/**
     * 该函数限制用户主动建立实例
     */
    private Singleton() {}
    private static Singleton singleton = null;
    /**
     * 获取Singleton实例,也叫静态工厂方法
     * @return Singleton
     */
    public static synchronized Singleton getSingleton(){
        if(singleton==null){
            singleton=new Singleton();
        }
        return singleton;
    }
    
}

双重检查锁定

ps:已修正,仍不推荐使用,感谢
江南布衣
指正

具体可参考正确使用双重检查锁定和双重检验锁失效”的问题说明

/**
 * 描述:懒汉单例模式 ,双重检查锁定<p>
 * 做者: kimball <p>
 * E-mail: kimballlu@foxmail.com <p>
 * 日期:2016-11-16 下午4:30:32 <p>
 */
public class Singleton {

    /**
     * 该函数限制用户主动建立实例
     */
    private Singleton() {}

    private volatile static Singleton singleton = null;

    /**
     * 获取Singleton实例,也叫静态工厂方法
     * @return Singleton
     */
    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

}

静态内部类:静态内部类比双重检查锁定和在getInstance()方法上加同步都要好,实现了线程安全又避免了同步带来的性能影响

/**
 * 描述:懒汉单例模式 ,静态内部类<p>
 * 做者: kimball <p>
 * E-mail: kimballlu@foxmail.com <p>
 * 日期:2016-11-16 下午4:30:32 <p>
 */
public class Singleton {

    /**
     * 静态内部类
     * @author kimball
     *
     */
    private static class LazyHolder {
        // 建立Singleton实例
        private static final Singleton INSTANCE = new Singleton();
    }

    /**
     * 该函数限制用户主动建立实例
     */
    private Singleton() {}

    /**
     * 获取Singleton实例,也叫静态工厂方法
     * @return Singleton
     */
    public static final Singleton getInstance() {
        return LazyHolder.INSTANCE;
    }

}

二、饿汉单例模式

/**
 * 描述:饿汉单例模式<p>
 * 做者: kimball <p>
 * E-mail: kimballlu@foxmail.com <p>
 * 日期:2016-11-16 下午4:30:32 <p>
 */
public class Singleton {

    /**
     * 该函数限制用户主动建立实例
     */
    private Singleton() {}

    private static final Singleton singleton = new Singleton();

    /**
     * 获取Singleton实例,也叫静态工厂方法
     * @return Singleton
     */
    public static Singleton getInstance() {
        return singleton;
    }

}

三、登记单利模式

/**
 * 描述:登记单例模式<p>
 * 做者: kimball <p>
 * E-mail: kimballlu@foxmail.com <p>
 * 日期:2016-11-16 下午4:30:32 <p>
 */
public class Singleton {

    // 存储须要进行维护和管理的类的实例
    private static Map<String, Singleton> map = new HashMap<String, Singleton>();
    
    /**
     * 静态建立实例并添加到Map集合
     */
    static {
        Singleton singleton = new Singleton();
        map.put(singleton.getClass().getName(), singleton);
    }

    /**
     * 该函数限制用户主动建立实例
     */
    private Singleton() {};

    /**
     * 获取Singleton实例,也叫静态工厂方法
     * @return Singleton
     */
    public static Singleton getInstance(String name) {
        /* 根据指定的类的名称从mao中获取实例并返回 */
        return map.get(name);
    }

    // 一个示例性的商业方法
    public String about() {
        return "你好,我是RegSingleton";
    }

    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance("com.Singleton");
        System.out.println(singleton.about());
    }

}

3、结语

以上就是单例设计模式,虽然单例设计模式是23种设计模式种比较简单的设计模式。可是三个臭皮匠也能顶一个诸葛亮,它天然有它存在的道理。

设计模式说白点就是编码的一种思惟(以前在学校老师一个劲儿的说思惟思惟,如今我也开始说,手动滑稽)

我是以生活的角度去看待编码,编码就是世界的缩小版

4、补充

上述讲的几种单例模式实现中,有一种状况下他们会从新建立对象,那就是反序列化,将一个单例实例对象写到磁盘再读回来,从而得到了一个实例。反序列化操做提供了readResolve方法,这个方法可让开发人员控制对象的反序列化。在上述的几个方法示例中若是要杜绝单例对象被反序列化是从新生成对象,就必须加入以下方法:

private Object readResolve() throws ObjectStreamException{
return singleton;
}

以上摘自https://blog.csdn.net/itachi8...
**一、因为enum是经过继承了Enum类实现的,enum结构不可以做为子类继承其余类,可是能够用来实现接口。此外,enum类也不可以被继承。
二、enum有且仅有private的构造器,防止外部的额外构造**

补充一种枚举实现的单例模式。

public enum  SingletonEnum {
    INSTANCE;
}

这样就实现完了,调用以下

@Test
    void singleton(){

        SingletonEnum instance = SingletonEnum.INSTANCE;
    }

对于序列化和反序列化,由于每个枚举类型和枚举变量在JVM中都是惟一的,即Java在序列化和反序列化枚举时作了特殊的规定,枚举的writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法是被编译器禁用的,所以也不存在实现序列化接口后调用readObject会破坏单例的问题。
以上摘自https://www.cnblogs.com/cielo...

若是文章对您有帮助,请记得点赞关注哟~ 欢迎你们关注个人公众号<情系IT>,每日推送技术文章供你们学习参考。
相关文章
相关标签/搜索