设计模式系列--23种常见设计模式之单例模式(11)

单例模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点。
Java中单例模式定义:“一个类有且仅有一个实例,并且自行实例化向整个系统提供。”

所有类都有构造方法,不编码则系统默认生成空的构造方法,若有显示定义的构造方法,默认的构造方法就会失效。

分析:

1、通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象;

一个最好的办法就是,让类自身负责保存它的唯一实例;这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。

2、单例模式因为封装了它的唯一实例,这样它可以严格地控制客户怎样访问它以及何时访问它。简单地说就是对唯一实例的受控访问。


实用类与单例区别?

比如实用类不保存状态,仅提供一些静态方法或静态属性让你使用,而单例类是有状态的;
实用类不能用于继承多态,而单例虽然实例唯一,却是可以有子类来继承。
实用类只不过是一些方法属性的集合,而单例却是有着唯一的对象实例。

单例模式的几种实现方式:

懒汉式:

package cn.pers.sample.singleton;

/**
 * 懒汉式.用的时候再加载。<br/>
 * (线程安全与否,与实现方式有关。调用效率不高,但是能延时加载)
 * @author WeiSong <br>
 * @since 0.0.1
 * 2020/11/12 15:29
 */
public class SingletonLazy {

    private static SingletonLazy instance;

    private SingletonLazy() {
    }

    public static SingletonLazy getInstance() {
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }

    //实现方式二  安全的实现方式
//    public static synchronized SingletonLazy getInstance() {
//        if (instance == null) {
//            instance = new SingletonLazy();
//        }
//        return instance;
//    }
}

饿汉式:

package cn.pers.sample.singleton;

/**
 * 饿汉式。提前加载好,用的时候直接取 <br/>
 * (线程安全,调用效率高,但是不能延时加载)
 * @author WeiSong <br>
 * @since 0.0.1
 * 2020/11/12 15:31
 */
public class SingletonHungry {

    private static SingletonHungry instance = new SingletonHungry();

    private SingletonHungry() {
    }

    public static SingletonHungry getInstance() {
        return instance;
    }
}

双重检查:

package cn.pers.sample.singleton;

/**
 * 基于懒汉式的双重检查.用的时候再加载,避免出现多线程同时创建。<br/>
 * (相对线程安全,但某些场景下也会有问题)
 * @author WeiSong <br>
 * @since 0.0.1
 * 2020/11/12 15:33
 */
public class SingletonDoubleCheck {

    private static SingletonDoubleCheck instance;

    private SingletonDoubleCheck() {
    }

    public static SingletonDoubleCheck getInstance() {
        if (instance == null) {
            synchronized (SingletonDoubleCheck.class) {
                if (instance == null) {
                    instance = new SingletonDoubleCheck();
                }
            }
        }
        return instance;
    }
}

静态内部类:

package cn.pers.sample.singleton;

/**
 * 静态内部类。<br/>
 * (线程安全,调用效率高,可以延时加载)
 * @author WeiSong <br>
 * @since 0.0.1
 * 2020/11/12 15:35
 */
public class SingletonInnerStatic {

    private SingletonInnerStatic() {
    }

    public static SingletonInnerStatic getInstance() {
        return SingletonHolder.instance;
    }

    private static class SingletonHolder {
        private static SingletonInnerStatic instance = new SingletonInnerStatic();
    }
}

枚举式:

package cn.pers.sample.singleton;

/**
 * 枚举式<br/>
 * (线程安全,调用效率高,不能延时加载,自动支持序列化机制,绝对防止多次实例化,防止反射和反序列化调用)
 * effective java中建议使用枚举. 枚举中创建的,在虚拟机中都是 final 和 static的,所以是安全的
 *
 * @author WeiSong <br>
 * @since 0.0.1
 * 2020/11/12 15:31
 */
public enum SingletonEnum {

    /** 枚举对象 */
    INSTANCE;

    public void method() {
        System.out.println("this is my define methods..");
    }

    /**
     * 使用方式.
     * @param args
     */
    public static void main(String[] args) {
        SingletonEnum.INSTANCE.method();

    }
}

综上,建议使用 枚举和内部类。


 

猜你喜欢

转载自blog.csdn.net/weisong530624687/article/details/109824297