设计模式2 单例模式
解决的问题
单例模式解决的问题就是:保证一个类只能实例化一个对象。
实现方法
一般我们保证一个类只有一个实例化对象时,做法是:
public class car{
private Brake brake;
public void useBreak(){
if (brake == null)
brake = new Brake();
brake.run();
}
}
如果这个brake对象不是仅供这一个Car类使用类呢?这样做只保证了在一个car对象有一个brake,多个car对象或者其他使用brake的类实例就会有多个brake出现了(当然这里的例子不好,本来就是一辆车子一个刹车)。所以我们不能把 保证只有一个实例的权利交给别人,应该让类自己来保证只实例化一个对象。
目前有这样几类方法:
懒汉法
懒汉法就是等到你需要一个单例实例的时候,我才会去实例化一个对象来给你。
public final class Singleton{
private static Singleton singleton;
private Singleton(){};
public static Singleton getSingleton(){
if (singleton == null)
singleton = new Singleton();
return singleton;
}
}
饿汉法
饿汉法是先帮你实例化一个对象,你需要的时候就向我拿。饿汉法有如下几种实现方法:
下面这种方法是最简单也是最好理解的,但是在多线程的情况存在安全隐患。
public final class Singleton{
private static Singleton singleton = new Singleton();
private Singleton(){};
public static Singleton getSingleton(){
return singleton;
}
}
下面这种方法利用了类在初始化时通过
public final void Singleton{
private static Singleton singleton;
static{
singleton = new Singleton();
}
private Singleton(){};
public static Singleton getSingleton(){
return singleton;
}
}
下面这种方式是以enum(枚举)的方式实现,它是实现单例模式的最佳方式。这种实现方式在多线程,序列化情况下依旧是安全的。
public enum Singleton{
SINGLETON;
// 接下来就是定义变量和方法(值得注意的是:变量和方法最好不是静态,不然SINGLETON无法使用,只能通过Singleton使用静态变量和方法)
}
双检锁
双检锁是考虑到多线程的懒汉法。
public final class Singleton{
private static Singleton singleton;
private Singleton(){};
private static Singleton getSingleton(){
if (singleton == null){
sychronized(Singleton.class){
if (singleton == null)
singleton = new Singleton();
}
}
return singleton;
}
}
要点
-
保证单例的构造方法为private,这样就不能通过new来实例化单例(当然通过反射还是可以实例化多个对象)
-
保证单例是不能被继承的。
-
保证在获得单例实例的函数返回实例之前实例化实例。
这样实现的益处
-
控制资源的使用,通过线程同步来控制资源的并发访问
-
控制实例的产生,以达到节约资源的目的
-
控制数据的共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信