单例模式提供了一种方式使得对象唯一化,一个类只能创建唯一一个实例。单例模式只包含一个Singleton(单例类),在单例类内部实现只生成一个实例,通过一个私有的构造函数,确保用户无法通过new关键字直接实例化单例类,而是通过一个静态的工厂方法来检测实例是否存在并实例化自己,然后储存在静态成员变量中,以确保只有一个实例被创建。
//一般结构
public class Singleton {
private static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
具体实例
public class IdentityCardNo {
private static IdentityCardNo instance = null;
private String no;
private IdentityCardNo(){
}
public static synchronized IdentityCardNo getInstance(){
if(instance == null){
System.out.println("第一次办理身份证,分配新号码");
instance = new IdentityCardNo();
instance.setIdentityCardNo("No123456789");
}
else {
System.out.println("重复办理");
}
return instance;
}
private void setIdentityCardNo(String no){
this.no = no;
}
public String getIdentityCardNo(){
return this.no;
}
}
单例模式的优点:
(1)提供了对唯一实例的访问控制,因为单例类封装了它唯一的实例,所以它可以严格控制客户怎样访问以及何时访问它。
(2)允许可变数目的实例。基于单例模式我们可以进行扩展,使用与单例模式相似的方法来获得指定数目的对象实例。
单例模式的缺点:
(1)单例模式没有抽象层,因此单例类扩展很难。
(2)单例类违背了“单一职责原则”。因为单例类既充当了工厂角色,又充当了产品角色。
(3)滥用单例模式会造成一些负面问题,为了节省资源将数据库连接池设计成单例类可能导致共享连接池对象的程序过多而出现连接池溢出。
(4)垃圾回收技术可能将实例化对象回收,下次利用时又重新实例化,这样造成对象状态的丢失。
适用环境:
(1)系统只需要一个实例对象。
(2)客户调用类的单个实例只允许使用一个公共访问点,除了这个访问点其他途径不能访问实例。
最好使用
饿汉式单例模式
//线程安全,不用加锁都安全,多线程可以直接用
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton(){}
public static EagerSingleton getInstance(){
return instance;
}
}
饱汉单例模式
//实现方法一
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton(){}
synchronized public static LazySingleton getInstance(){
if(instance == null){
instance = new LazySingleton();
}
return instance;
}
}
//实现方法二
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton(){}
public static LazySingleton getInstance() {
if (instance == null) {
synchronized (LazySingleton.class) {
if (instance == null) {
instance = new LazySingleton();
}
}
}
return instance;
}
}
//实现方法三
public class LazySingleton {
private static class LazySingletonCreat{
private static final LazySingleton INSTANCE = new LazySingleton();
}
private static LazySingleton INSTANCE = null;
private LazySingleton(){}
public static LazySingleton getInstance() {
return LazySingletonCreat.INSTANCE;
}
}