单例模式(Singletion),我估计大家用到比较多.我使用的第一个设计模式就是单利模式.
单例模式是为了确保一个类有且仅有一个实例,并为它提供一个全局访问点.简单说就是你不能new一个实例出来.
举一个例子,比如在我的开发中有这样一种情况,我们有同事写了一组地图工具MapUtils.java,我们在不同的使用地方来调用这个工具类,为了避免有多个工具类实例存在就使用单利模式.
一、懒汉单利模式模式
public class MapUtils { private MKSearch mkSearch; private LocationClient locationClient; private OnLocationListener listener; private static MapUtils instance; private MapUtils() { } public static MapUtils getInstance(Context context) { if (null == instance) { instance = new MapUtils(context.getApplicationContext()); } return instance; }}
构造函数为private,这样就不能使用new来创建实例.唯一实例只能通过getInstance()方法访问。(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论.)
上面的单例模式为懒汉单例模式,懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个MapUtils实例,要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全,如果你第一次接触单例模式,对线程安全不是很了解,可以先跳过下面这三小条,去看饿汉式单例,等看完后面再回头考虑线程安全的问题.
1、在getInstance方法上加同步
public static synchronized MapUtils getInstance(Context context) { if (null == instance) { instance = new MapUtils(context.getApplicationContext()); } return instance; }
2、双重检查锁定
public static MapUtils getInstance(Context context) { if (null == instance) { synchronized (MapUtils.class) { if (null == instance) { instance = new MapUtils(context.getApplicationContext()); } } } return instance;}
3、静态内部类
public class MapUtils { private static class LazyHolder { private static Context context; private static final MapUtils INSTANCE = new MapUtils(context.getApplicationContext()); } private MapUtils(Context context){} public static final MapUtils getInstance(Context context) { LazyHolder.context = context; return LazyHolder.INSTANCE; }}
二、饿汉式单例模式
//饿汉式单例类.在类初始化时,已经自行实例化
public class MapUtils { private MapUtils() {} private static final MapUtils instance = new MapUtils(); //静态工厂方法 public static MapUtils getInstance() { return instance; } }
饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。 还有一种登记式单例模式.没有细细去看就不做介绍了.
什么是线程安全? 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。 或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。
PS:对于设计模式我只是作为学习笔记来写的,并非网上大牛们的手笔,所以各位看官看看就行,有错误请多多指正,要真正学习设计模式,书籍有,《大话设计模式》,这个需要C++语言底子,《您的设计模式》这个讲解的很有风趣,没有《大话设计模式》讲解的深,还有一本《Head First 设计模式》也讲解的蛮有意思的。