其他分享
首页 > 其他分享> > 开发模式)Note6)单例模式的实现

开发模式)Note6)单例模式的实现

作者:互联网

内容均为网上收集整理,供自己学习做笔记使用

一,什么是单例模式

  Java中的单例模式是一种非常常见的设计模式,单例模式的写法有很多种,本次主要实现懒汉、饿汉式单例,登记式单例。单例模式的特点有:

  1. 单例类只能有一个实例。
  2. 单例类必须自己来创建自己的唯一实例。
  3. 单例类必须要给所有其他对象提供这一实例。

  单例模式确保每个类都只有一个实例,而且自行实例并向整个系统提供这个实例。在计算机系统中比如线程池、缓存、日志等对象常被设计称为单例的。单例模式的出现就是为了避免不一致的状态,避免政出多头。

二,懒汉式单例实现

package one.example;
/**
 * 懒汉式单例类,在第一次调用的时候实例化自己
 * @author ShadowY
 *
 * 2021年8月24日 下午6:56:08
 */
public class Singleton {
	private Singleton() {};
	private static Singleton singleton = null;
	//静态工厂方法
	public static Singleton getInstance() {
		if (singleton == null) {
			singleton = new Singleton();
		}
		return singleton;
	}
}

  Singleton将自己的构造方法限定为private的,这样可以避免类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例之鞥呢通过getInstance()方法来访问。(事实上这样做并不是绝对安全的,通过Java反射机制是可以实例化构造方法为private的类的,那基本会使所有的Java单例实现失效。)
  上述的懒汉式单例模式并没有考虑到线程安全问题,在并发度较高的环境下,可能会出现不止一个的Singleton实例。

  1. 给getInstance()方法加上同步,保证同时间下只有一条线程能进来:
public static synchronized Singleton getInstance() {
	if (singleton == null) {
		singleton = new Singleton();
	}
	return singleton;
}
  1. 双重检查(其实还是同步):
public static synchronized Singleton getInstance() {
	if (singleton == null) {
		synchronized (Singleton.class){
			if (singleton == null){
				singleton = new Singleton();
			}
		}
	}
	return singleton;
}
  1. 静态内部类
public class Singleton {
    private static class LazyHolder {  
       private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
       return LazyHolder.INSTANCE;  
    }  
}

三,饿汉单例实现

package one.example;
/**
 * 饿汉式单例类,在类进行初始化的时候,就会自行实例化
 * @author ShadowY
 *
 * 2021年8月24日 下午7:37:56
 */
public class Singleton {
	private Singleton() {}
	private static final Singleton SINGLETON = new Singleton();
	//静态工厂方法
	public Singleton getInstance() {
		return SINGLETON;
	}
}

  饿汉式在类创建的时候就已经创建好了一个静态的对象供我们使用,用final修饰表明后面不会再发生改变,通过这种方法可以不需要考虑线程安全的问题。

四,登记式单例

//类似Spring里面的方法,将类名注册,下次从里面直接获取。
public class Singleton3 {
    private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
    static{
        Singleton3 single = new Singleton3();
        map.put(single.getClass().getName(), single);
    }
    //保护的默认构造子
    protected Singleton3(){}
    //静态工厂方法,返还此类惟一的实例
    public static Singleton3 getInstance(String name) {
        if(name == null) {
            name = Singleton3.class.getName();
            System.out.println("name == null"+"--->name="+name);
        }
        if(map.get(name) == null) {
            try {
                map.put(name, (Singleton3) Class.forName(name).newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return map.get(name);
    }
    //一个示意性的商业方法
    public String about() {    
        return "Hello, I am RegSingleton.";    
    }    
    public static void main(String[] args) {
        Singleton3 single3 = Singleton3.getInstance(null);
        System.out.println(single3.about());
    }
}

五,实际应用

package one.example;
/**
 * 懒汉式单例类
 * @author ShadowY
 *
 * 2021年8月24日 下午7:47:03
 */
public class Singleton {
	String name = null;
    private Singleton(){}

    private static volatile Singleton singleton = null;

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

	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public void printInfo() {
		System.out.println("the name is " + name);
	}

}
package one.example;
/**
 * Singleton类的测试类
 * @author ShadowY
 *
 * 2021年8月24日 下午7:48:51
 */
public class SingletonTest {
	public static void main(String[] args) {
		Singleton st1 = Singleton.getInstance();
		st1.setName("I'am ST1");
		Singleton st2 = Singleton.getInstance();
		st2.setName("I'am ST2");	//ST1与ST2其实是一个实例,调用的其实是一个实例,会覆盖之前的
		
		st1.printInfo();
		st2.printInfo();
		
		if (st1==st2) {
			System.out.println("st1和st2其实是一个实例");
		}else {
			System.out.println("st1和st2是两个不同的实例");
		}
	}
}

//the name is I'am ST2
//the name is I'am ST2
//st1和st2其实是一个实例

  总结:单例模式为一个面向对象的应用程序提供了对象唯一的访问点,无论实现何种功能,整个应用程序都会共享用一个实例对象。对于这两种实现方式,要知道饿汉式与懒汉式的区别、线程安全、资源加载的实际以及懒汉式实现线程安全的方式。

标签:Singleton,name,singleton,模式,Note6,static,单例,public
来源: https://blog.csdn.net/zy_zhangruichen/article/details/119896801