您的位置:首页 > 移动开发 > Android开发

Android进阶系列之源码SDK单例模式运用

2016-12-27 18:13 316 查看
又到了伤心时刻,源码的魅力,只有翱翔于源码的海洋时才能发现。震惊于她的美丽,她的性感,她的婀娜多姿。是的,是她。



在看源码之前呢,我们对单例模式应该有足够了解才能在一片黑的源码中找到那点光亮。单例模式,就如它的名字一样,没有必要多次实例化,一次就好。
那么单例模式又有多少种呢。除去变异的大概有5种。简单单例模式,饿汉单例模式,DLC单例模式,内部类单例模式,枚举类单例模式。还有很多这些变异的单例,就不一一举例了。
那么开始上代码。简单单例模式
package com.example.administrator.singleinstance;

import android.util.Log;

/**
* Created by Administrator on 2016/12/26.
*/

public class SimpleInstance extends Instance{
public SimpleInstance(){}
private static SimpleInstance INSTANCE;

public static SimpleInstance getInstance(){
INSTANCE = new SimpleInstance();
return INSTANCE;
}

@Override
public void doSomething(){
Log.i("tag00","简单单例模式");
}
}
饿汉单例模式,线程安全
package com.example.administrator.singleinstance;

import android.util.Log;

/**
* Created by Administrator on 2016/12/26.
*/

public class HungryInstance extends Instance{
private static HungryInstance instance;
public HungryInstance(){}

public static HungryInstance getInstance(){
synchronized (HungryInstance.class){
if (instance == null){
instance = new HungryInstance();
}
return instance;
}
}

@Override
public void doSomething(){
Log.i("tag00","饿汉单例模式");
}
}


DLC单例模式,在饿汉的基础上进行二次判断和加了同步锁。线程安全
package com.example.administrator.singleinstance;

import android.util.Log;

/**
* Created by Administrator on 2016/12/26.
*/

public class DLCInstance extends Instance{
//这里的volatile是为了避免高并发时出现乱序
private static volatile DLCInstance instance;
public DLCInstance(){}
public static DLCInstance getInstance(){
if (instance == null){
synchronized (DLCInstance.class){
if (instance == null){
instance = new DLCInstance();
}
}
}
return instance;
}
@Override
public void doSomething(){
Log.i("tag00","DLC单例模式");
}
}
内部类单例模式,使用静态内部类来创建单例
package com.example.administrator.singleinstance;

import android.util.Log;

/**
* Created by Administrator on 2016/12/26.
*/

public class InnerInstance extends Instance{

public InnerInstance() {
}

private static class InnerClass{
public static InnerInstance instance = new InnerInstance();
}

public static InnerInstance getInstance(){
synchronized (InnerInstance.class){
return InnerClass.instance;
}
}

@Override
public void doSomething(){
Log.i("tag00","内部类单例模式");
}
}
枚举类单例模式,很多人都推崇静态内部类和枚举类单例。原因当然是线程和资源加载性能方面,只有出现高并发的时候或者不同线程并发的时候才能体现出来,一般小项目是看不出来的。
package com.example.administrator.singleinstance;

import android.util.Log;

/**
* Created by Administrator on 2016/12/27.
*/

public enum EnumInstance {
INSTANCE;
public void doSomething(){
Log.i("tag00","枚举单例模式");
}
}
这里我所有的单例都继承了一个抽象父类,这样就可以统一管理所有单例类。如果需要统一加功能,只需要在父类中加就行。或者个别的加接口就行。写一个Map来管理单例。
package com.example.administrator.singleinstance;

/**
* Created by Administrator on 2016/12/27.
*/

public abstract class Instance {
abstract void doSomething();
}
package com.example.administrator.singleinstance;

import java.util.HashMap;
import java.util.Map;

/**
* Created by Administrator on 2016/12/27.
*/

public class InstanceManager {
private static Map<String,Object>instanceMap = new HashMap<>();

public static void init(){
instanceMap.put(SimpleInstance.class.getName(),SimpleInstance.getInstance());
instanceMap.put(DLCInstance.class.getName(),DLCInstance.getInstance());
instanceMap.put(EnumInstance.class.getName(),EnumInstance.INSTANCE);
instanceMap.put(HungryInstance.class.getName(),HungryInstance.getInstance());
instanceMap.put(InnerInstance.class.getName(),InnerInstance.getInstance());
}

public static Instance getInstance(String InstanceName){
return (Instance) instanceMap.get(InstanceName);
}

public static EnumInstance getEnumInstance(String InstanceName){
return (EnumInstance) instanceMap.get(InstanceName);
}

}
在InstanceManager中以单例类名作为Key,对象Object作为Value。在取的时候以单例类名就可以取了,也许在这个例子里看这样有点多余,但是当项目大了,单例类多了这样就便于管理。

基本的单例模式就这些了,具体就是看使用时遇见啥问题,具体问题具体处理。那么开始撸源码。看看Intent的单例是怎么回事呢、

在SDK的source文件夹下搜索InputMethodManager。这个类看看这个类怎么运用单例的。
public final class InputMethodManager {
static final boolean DEBUG = false;
static final String TAG = "InputMethodManager";

static final String PENDING_EVENT_COUNTER = "aq:imm";

static InputMethodManager sInstance;
.......
}首先创建一个静态的实例对象,真正的逻辑还在下面、



先判断实例是否为null,如果为null就新创建一个实例,不为null就返回。这就是典型的饿汉单例模式的运用。
再看看AccessibilityManager类,这里面也用了单例模式。





使用的是简单单例模式(懒汉),直接给实例化。简单暴力,至于什么时候该加线程锁,什么时候使用什么模式好,这里我不再赘述,我找到一篇博客有相应的介绍,待会会放在最后大家有兴趣了解可以去看看。这个要从java的JVM和内存分配说起。还有很多很多使用了单例模式的源码,碍于我对源码的不熟悉,只能写到这儿了。最后附上那个博客地址:http://www.iteye.com/topic/575052。写的不错。
设计模式在Android架构的运用很是重要,望重视。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息