参考:http://blog.csdn.net/jason0539/article/details/23297037/
单例模式:指的是一个类只有一个实例对象。它的设计是为了实现类的单一功能。专注于自己的事情。
有如下三个特点:
- 单例类只有一个实例
- 单例类必须自己创建这一个实例
- 单例类必须将自己的这个实例提供给其他对象
因此我们在实现单例类的时候要注意一下几点:
- 首先禁止他人创建实例对象,故它的构造函数必须是私有的;
- 其次自己创建实例要在类加载时创建,故必须有一个静态的实例对象的成员变量;
- 要给他人提供实例,故要有一个获取该方法的公有成员方法。
常见的单例模式的实现有5中方法
- 懒汉式:需要时创建实例,线程不安全
- 饿汉式:类加载时就创建,线程不安全
- 使用同步方法的懒汉式
- 使用双重检查加锁的懒汉式
- 使用静态内部类的懒汉式(这个比较推荐)
下面将一一实现:
一、懒汉式
public class Singleton1 {
private Singleton1(){
}
private static Singleton1 instance = null;
//测试方法
public void sayHello(String name){
System.out.println("Hello, " + name);
}
/**
* 线程不安全的写法
* @return
*/
public static Singleton1 getInstance(){
if(instance == null){
instance = new Singleton1();
}
return instance;
}
}
测试:
public class TestSingleton1 {
public static void main(String[] args){
Singleton1 ins = Singleton1.getInstance();
ins.sayHello("Mike");
Singleton1 ins2 = Singleton1.getInstance();
ins2.sayHello("Mike");
if(ins == ins2){
System.out.println("同一个实例");
}else{
System.out.println("不同的实例");
}
}
二、饿汉式
public class Singleton2 {
private Singleton2(){
}
private static Singleton2 instance = new Singleton2();
private static Singleton2 getInstance(){
return instance;
}
}
三、懒汉式+同步机制
public class Singleton1 {
private Singleton1(){
}
private static Singleton1 instance = null;
//测试方法
public void sayHello(String name){
System.out.println("Hello, " + name);
}
public static synchronized Singleton1 getInstance(){
if(instance == null){
instance = new Singleton1();
}
return instance;
}
}
四、懒汉式+双重检查锁定
public class Singleton1 {
private Singleton1(){
}
private static Singleton1 instance = null;
//测试方法
public void sayHello(String name){
System.out.println("Hello, " + name);
}
public static Singleton1 getInstance(){
if(instance == null){
synchronized(Singleton1.class){
if(instance == null){
instance = new Singleton1();
}
}
}
return instance;
}
}
五、懒汉式+静态内部类
public class Singleton1 {
private Singleton1(){
}
private static Singleton1 instance = null;
//测试方法
public void sayHello(String name){
System.out.println("Hello, " + name);
}
private static class LazyHolder{
private static final Singleton1 INSTANCE = new Singleton1();
}
public static Singleton1 getInstance(){
return LazyHolder.INSTANCE;
}
}
六、登记式单例类
package designpattern.singleton;
import java.util.HashMap;
import java.util.Map;
/**
* 登记式单例模式
* @author wenbaoli
*
*/
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());
}
}
测试:
public class TestSingleton3 {
public static void main(String[] args){
Singleton3 single1 = Singleton3.getInstance(null);
System.out.println(single1.about());
System.out.println("------------我是分割线----------");
Singleton3 single2 = Singleton3.getInstance(single1.getClass().getName());
System.out.println(single1.about());
if(single1 == single2){
System.out.println("他们是同一个实例");
}else{
System.out.println("他们是不同的实例");
}
}
}
附录:查漏补缺——代码中我不熟悉或不知道的事
name = Singleton3.class.getName();
: 表示获取Singleton3这个类的名字。一个类的name是它所在的包名.类名(Singleton3) Class.forName(name).newInstance()
: 表示去加载name(包名.类名)的下的这个类。。。
例如:给你一个字符串变量,它代表一个类的包名和类名,你怎么实例化它?只有你提到的这个方法了,不过要再加一点。 A a = (A)Class.forName(“pacage.A”).newInstance(); 这和你 A a = new A(); 是一样的效果。