ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-08-24 20:04:32  阅读:121  来源: 互联网

标签:Singleton name singleton 模式 Note6 static 单例 public


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

一,什么是单例模式

  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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有