Singleton 单例模式

饿汉式单例模式
package com.sheting.design.pattern.creational.singleton;

/**
 * Create Time: 2018-03-17 10:01
 *
 * @author sheting
 */
public class EagerInitializedSingleton {

    /**
    立即生成单例对象
     */
    private static final EagerInitializedSingleton instance = new EagerInitializedSingleton();

    /**
     * private constructor to avoid client applications to use constructor
     */
    private EagerInitializedSingleton(){}

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

饿汉式单例模式 通过静态代码块增加异常处理
package com.sheting.design.pattern.creational.singleton;

/**
 * Create Time: 2018-03-17 10:03
 *
 * @author sheting
 */
public class StaticBlockSingleton {

    private static StaticBlockSingleton instance;

    private StaticBlockSingleton(){}

    //增加异常处理
    static{
        try{
            instance = new StaticBlockSingleton();
        }catch(Exception e){
            throw new RuntimeException("Exception occured in creating singleton instance");
        }
    }

    public static StaticBlockSingleton getInstance(){
        return instance;
    }

}

懒汉式单例模式 存在线程安全问题
package com.sheting.design.pattern.creational.singleton;

/**
 * Create Time: 2018-03-17 10:04
 *
 * @author sheting
 */
public class LazyInitializedSingleton {

    private static LazyInitializedSingleton instance;

    private LazyInitializedSingleton(){}

    //存在线程安全问题
    public static LazyInitializedSingleton getInstance(){
        if(instance == null){
            instance = new LazyInitializedSingleton();
        }
        return instance;
    }

}

懒汉式单例模式 解决线程安全问题
package com.sheting.design.pattern.creational.singleton;

/**
 * Create Time: 2018-03-17 10:06
 *
 * @author sheting
 */
public class ThreadSafeSingleton {

    private static ThreadSafeSingleton instance;

    private ThreadSafeSingleton(){}

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

    //和上面的方法相比,性能提升了,因为synchronized只获取一次,上面方法,每次调用getInstance都要检查锁
    public static ThreadSafeSingleton getInstanceUsingDoubleLocking(){
        if(instance == null){
            synchronized (ThreadSafeSingleton.class) {
                if(instance == null){
                    instance = new ThreadSafeSingleton();
                }
            }
        }
        return instance;
    }
}

内部静态类实现的单例模式
package com.sheting.design.pattern.creational.singleton;

import com.sheting.singleton.Singleton;

/**
 * Create Time: 2018-03-17 10:14
 *
 * @author sheting
 */
public class BillPughSingleton {

    private BillPughSingleton(){}

  /*
    Notice the private inner static class that contains the instance of the singleton class.
    When the singleton class is loaded, SingletonHelper class is not loaded into memory and only when someone calls the getInstance method,
    this class gets loaded and creates the Singleton class instance.

    This is the most widely used approach for Singleton class as it doesn’t require synchronization.
    I am using this approach in many of my projects and it’s easy to understand and implement also.
    */

    //内部静态类实现单例
    private static class SingletonHelper{
        private static final BillPughSingleton INSTANCE = new BillPughSingleton();
    }

    public static BillPughSingleton getInstance(){
        return SingletonHelper.INSTANCE;
    }

}

枚举天然的单例模式
package com.sheting.design.pattern.creational.singleton;

/**
 * Create Time: 2018-03-17 10:21
 *
 * @author sheting
 */
public enum EnumSingleton {

    //枚举三个特性,自由序列化,线程安全,保证单例。
    INSTANCE;

    public static void doSomething(){
        //do something
    }
}

单例对象 实现序列化接口 不实现readResolve(),返回的hashCode值不一样
package com.sheting.design.pattern.creational.singleton;

import java.io.*;

/**
 * Create Time: 2018-03-17 10:33
 *
 * @author sheting
 */
public class SingletonSerializedTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        SerializedSingleton instanceOne = SerializedSingleton.getInstance();
        ObjectOutput out = new ObjectOutputStream(new FileOutputStream("filename.ser"));
        out.writeObject(instanceOne);
        out.close();

        //deserailize from file to object
        ObjectInput in = new ObjectInputStream(new FileInputStream("filename.ser"));
        SerializedSingleton instanceTwo = (SerializedSingleton) in.readObject();
        in.close();

        System.out.println("instanceOne hashCode="+instanceOne.hashCode());
        System.out.println("instanceTwo hashCode="+instanceTwo.hashCode());


      /* API解释:
      从 ObjectInputStream 读取“非共享”对象。此方法与 readObject 类似,
      不同点在于它可以防止对 readObject 和 readUnshared 的后续调用返回对通过此调用获取的反序列化实例的附加引用。尤其是:
         如果调用 readUnshared 反序列化反向引用(以前写入流的对象的流表示形式),则抛出 ObjectStreamException。
         如果 readUnshared 成功返回,则反序列化对由 readUnshared 反序列化的流句柄的反向引用的任何后续尝试,都将导致抛出 ObjectStreamException。
      通过 readUnshared 反序列化一个对象使得与返回对象关联的流句柄无效。
      注意,此操作本身不能始终保证由 readUnshared 返回的引用是唯一的;反序列化对象可能定义一个 readResolve 方法,
      该方法将返回一个对其他方可见的对象,或者 readUnshared 可能返回一个从流中其他地方或通过外部方法获得的 Class 对象或 enum 常量。
      如果反序列化对象定义一个 readResolve 方法并且该方法的调用返回一个数组,则 readUnshared 返回该数组的浅表副本;
      此规则保证返回的数组对象是唯一的,不能通过对 ObjectInputStream 调用 readObject 或 readUnshared 再次获得,即使能操纵底层数据流时也是如此。

      重写此方法的 ObjectInputStream 子类只能在处理 "enableSubclassImplementation" SerializablePermission 的安全上下文中构造;
      在不具有此权限的情况下,任何实例化这种子类的尝试都将导致抛出 SecurityException。

        */
    }
}

class SerializedSingleton implements Serializable {

    private static final long serialVersionUID = -7604766932017737115L;

    private SerializedSingleton(){}

    private static class SingletonHelper{
        private static final SerializedSingleton instance = new SerializedSingleton();
    }

    public static SerializedSingleton getInstance(){
        return SingletonHelper.instance;
    }

     //重要   
    protected Object readResolve() {
        return getInstance();
    }

}

你可能感兴趣的:(Singleton 单例模式)