[设计模式]单例模式(Java实现)

Jun 2, 2015


一、单例模式(也叫单态模式)

如果把Java的构造方法弄成private,那里面的成员属性是不是只有通过static来访问呢。如果构造方法是private的话,那么有什么好处呢。如果构造方法是private的话,会不更好的封装该类呢。 这就是单例模式。构造函数弄成private 就是单例模式,即不想让别人用new 方法来创建多个对象,可以在类里面先生成一个对象,然后写一个public static方法把这个对象return出去。

单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

简单实例:


public class single{   
    private static final single s=new single();   
    private single(){}   
    public static single getInstance(){   
        return s;   
    }   
}   

二、单例式概念及特点

java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。

单例模式有一下特点:

1.单例类只能有一个实例。

2.单例类必须自己自己创建自己的唯一实例。

3.单例类必须给所有其他对象提供这一实例。

懒汉式:

//懒汉式单例类.在第一次调用的时候实例化   
 public class Singleton2 {  
     private Singleton2() {}    
     private static Singleton2 single=null;  
     public synchronized  static Singleton2 getInstance() {  
          if (single == null) {    
              single = new Singleton2();  
          }    
         return single;  
     }  
}  

饿汉式:

//饿汉式单例类.在类初始化时,已经自行实例化   
 public class Singleton1{  
     private Singleton1(){}  
     private static final Singleton1 single = new Singleton1();  
     public static Singleton1 getInstance() {  
         return single;  
     }  
}  

登记式:

登记式实际对一组单例模式进行的维护,主要是在数量上的扩展,通过map我们把单例存进去,这样在调用时,先判断该单例是否已经创建,是的话直接返回,不是的话创建一个登记到map中,再返回。对于数量又分为固定数量和不固定数量的。下面采用的是不固定数量的方式,在getInstance方法中加上参数(string name)。然后通过子类继承,重写这个方法将name传进去。

public class Singleton3{  
    private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();  
    static{  
        Singleton3 single = new Singleton3();  
        map.put(single.getClass().getName(), single);  
    }  
    private Singleton3(){}  
    public static Singleton3 getInstance(String name){  
        if(name == null){  
            name = Singleton3.class.getName();  
            System.out.println(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());  
    }  
}  

三、使用时注意事项

1.使用时不能用反射模式创建单例,否则会实例化一个新的对象。

2.使用懒单例模式时注意线程安全问题。

3.饿单例模式和懒单例模式构造方法都是私有的,因而是不能被继承的,有些单例模式可以被继承(如登记式模式)。