1:单例类只能是一个实例
2:单例类必须自己创建自己的唯一实例
3:单例类必须给所有其他对象提供这一实例
注意:
1:不要使用单例模式存取全局变量最好放在对应类的静态成员中
2:不要将数据库连接做成单例,因为一个系统可能与数据库有多个连接,并且 在有连接池的情况下,应当尽可能及时释放连接。
单例模式在Java语言的实现上有三种情况:饿汉式单例类,懒汉式单例类,登记式单例类。
例子:
饿汉方式的单例模式的优缺点:
线程安全,但效率比较低,一开始就要加载类new一个对象 (饿汉式单例类饿汉式单例类是在Java 语言里实现得最为简便的单例类。在类被加载时,就会将自己实例化。)
public class Singleton{//私有的构造方
private Singleton(){}
private static Singleton instance=new Singleton();
//这里提供供外部访问本class静态的方法,可以直接访问
private static Singleton getInstance()
{
return instance;
}
}
懒汉式单例类优缺点:
是有多个线程访问时就不是安全的 返回的不是同一个对象(与饿汉式单例类不同的是,懒汉式单例类在第一次被引用时将自己实例化。)
public class Singleton{//定义Singleton的静态引用private static Singleton instance = null;
//构造方法私有,不能再外部直接调用创建实例
private Singleton(){}
//提供公共的静态的、同步的方法,获取Singleton的实例
public static Singleton getInstance(){
if(instance==null)
{
instance = new Singleton();
}
return instance;
}
}
登记式单例类
登记式单例类是为了克服饿汉式单例类及懒汉式单例类均不可继承的缺点而设计的。
JAVA代码:
package com.javapatterns.singleton.demos;
import java.util.*;
public class RegSingleton {
//静态的私有HashMap对象
static private HashMap m_registry = new HashMap();
//静态块,类加载时运行
static { //实例RegSingleton对象 RegSingleton x = new RegSingleton();
//将其存贮在map集合中 m_registry.put(x.getClass().getName(), x);
}
//受保护的构造方法,子类可以调用。
protected RegSingleton(){
}
//公共的静态方法,返回该类的实例
static public RegSingleton getInstance(String name) {
if (name == null) {
name = "com.javapatterns.singleton.demos.RegSingleton";
}
if (m_registry.get(name) == null) {
try {
// Class.forName(name).newInstance()通过类名得到类的实例
m_registry.put(name, Class.forName(name).newInstance());
}
catch (Exception e) {
System.out.println("Error happened.");
}
}
return (RegSingleton) (m_registry.get(name));
}
}