前言
单例设计模式(一) - 定义、volatile关键字好处
单例设计模式(二) - 常见几种写法
单例设计模式(三) - 强大的Activity的管理
1. 概述
上篇文章讲解了单例设计模式的套路及volatile作用,那么这篇文章就记录下单例设计模式常见的几种写法。
最常见的有3种:
1>: 单例 - 懒汉式(同步锁:DCL)
只有在使用的时候,才会去new 对象;
DCL定义:就是单例设计模式的懒汉式的同步锁方式
/**
* Email: 2185134304@qq.com
* Created by Novate 2018/5/6 11:15
* Version 1.0
* Params:
* Description: 单例 - 懒汉式: (同步锁:DCL)
* 只有在使用的时候,才会去new 对象
* DCL定义:就是单例设计模式懒汉式同步锁的方式
*/
public class SingleTon3 {
// 只有在使用的时候,才会去 new 对象,比较高效
// 但是会有问题? 多线程并发的问题,如果多线程调用还是会存在多个实例的
// 加上 volatile 好处是什么?
// 1.防止重新排序
private static volatile SingleTon3 mInstance ;
private SingleTon3(){
}
/**
* 双重校验加同步锁 synchronized:
* 既保证线程安全,同时也保证效率比较高
* 但是可能还会有问题,
*/
public static SingleTon3 getInstance(){
if (mInstance == null){
synchronized (SingleTon3.class){ // 这个if只能进来一次,第二次就不会进来了
if (mInstance == null){
mInstance = new SingleTon3() ;
}
}
}
return mInstance ;
}
}
2>:单例 - 静态内部类
- 保证线程的安全;
- 用到的时候才会去 new SingleTon()对象
/**
* Email: 2185134304@qq.com
* Created by Novate 2018/5/6 12:10
* Version 1.0
* Params:
* Description: 单例 - 静态内部类(比较常用)
* 1. 保证线程的安全;
* 2. 用到的时候才会 new SingleTon() 对象;
*/
public class SingleTon {
private SingleTon(){
}
public static SingleTon getInstance(){
return SingleTonHolder.mInstance ;
}
public static class SingleTonHolder{
private static volatile SingleTon mInstance = new SingleTon() ;
}
}
3>:单例 - 容器管理(系统服务就用的这种 getSystemService())
/**
* Email: 2185134304@qq.com
* Created by Novate 2018/5/6 12:10
* Version 1.0
* Params:
* Description: 单例 - 容器管理(系统服务里边用的这种 getSystemService())
*/
public class SingleTon {
private static Map<String , Object> mSingleMap = new HashMap<>() ;
private SingleTon(){
}
/**
* 用静态的方式把 SingleTon对象初始化好了
*/
static {
mSingleMap.put("activity_manager" , new SingleTon()) ;
}
public static Object getService(String serviceName){
return mSingleMap.get(serviceName) ;
}
}
几种不常用的单例写法:
1>:单例 - 懒汉式: 随着类的启动就已经 new 了 mInstance对象了
一般不会这么用,不太好;
/**
* Email: 2185134304@qq.com
* Created by Novate 2018/5/6 11:10
* Version 1.0
* Params:
* Description: 单例 - 饿汉式:随着类的启动就已经 new 了一个对象了 (一般不会这么用,不太好)
*/
public class SingleTon {
// 随着类的启动就已经 new 了一个对象了,但是可能我们只是想在用的时候再去 new 对象
private static SingleTon mInstance = new SingleTon();
private SingleTon(){
}
public static SingleTon getInstance(){
return mInstance ;
}
}
2>:单例 - 懒汉式:只有在使用的时候,才会去new 对象
/**
* Email: 2185134304@qq.com
* Created by Novate 2018/5/6 11:15
* Version 1.0
* Params:
* Description: 单例 - 懒汉式:只有在使用的时候,才会去new 对象
*/
public class SingleTon1 {
// 只有在使用的时候,才会去 new 对象,比较高效
// 但是会有问题? 多线程并发的问题,如果多线程调用还是会存在多个实例的
private static SingleTon1 mInstance ;
private SingleTon1(){
}
/**
* 加同步锁 synchronized:
* 虽然解决了线程安全的问题,但是率可能会比较低,
* 因为每次获取mInstance对象都要经过同步锁的判断;
*/
public static synchronized SingleTon1 getInstance(){
if (mInstance == null){
mInstance = new SingleTon1() ;
}
return mInstance ;
}
}
3>:单例 - 懒汉式:只有在使用的时候,才会去new 对象
/**
* Email: 2185134304@qq.com
* Created by Novate 2018/5/6 11:15
* Version 1.0
* Params:
* Description: 单例 - 懒汉式:只有在使用的时候,才会去new 对象
*/
public class SingleTon2 {
// 只有在使用的时候,才会去 new 对象,比较高效
// 但是会有问题? 多线程并发的问题,如果多线程调用还是会存在多个实例的
private static SingleTon2 mInstance ;
private SingleTon2(){
}
/**
* 双重校验加同步锁 synchronized:
* 既保证线程安全,同时也保证效率比较高
* 但是可能还会有问题,
*/
public static SingleTon2 getInstance(){
if (mInstance == null){
synchronized (SingleTon2.class){ // 这个if只能进来一次,第二次就不会进来了
if (mInstance == null){
mInstance = new SingleTon2() ;
}
}
}
return mInstance ;
}
}
4>:单例 - 自成一派写法
其实只要满足整个程序中只有一个实例对象就可以,代码可以随便写
/**
* Email: 2185134304@qq.com
* Created by Novate 2018/5/6 12:25
* Version 1.0
* Params:
* Description: 单例 - 自成一派
*/
public class SingleTon {
private static SingleTon mInstance ;
static {
mInstance = new SingleTon() ;
}
private SingleTon(){
}
public static SingleTon getInstance(){
return mInstance ;
}
}
代码已上传至github:
https://github.com/shuai999/Architect_day8.git