设计模式Android知识程序员

结合Android看看单例模式怎么写

2017-04-05  本文已影响884人  IAM四十二

定义及使用场景

定义

单例模式,就是在整个系统中某一个类的实例只有一个,并且自行实例化向整个系统提供;简单来说,就是某个类被实例化的方式是唯一的;同时他它必须向系统自动提供这个实例。

使用场景

常见的实现方式

下面是单例模式常见的两种实现方式 饿汉模式和 双重锁模式

public class HungrySingleton {

    private static HungrySingleton mInstance = new HungrySingleton();

    private HungrySingleton() {

    }

    public static HungrySingleton getInstance() {
        return mInstance;
    }
}

不得不说,饿汉模式这个名字起得的确很巧,这种方式,不管你用不用得着这个实例,先给你创建(new)出来,生怕将来创建没机会似得,完全就是今朝有酒今朝醉的节奏。

与上面对应的还有一种就是懒汉模式,就是在用的时候才在getInstance 方法中完成实例的创建(new),真是“懒”,同时给这个方法添加synchronized 关键字,可以确保在多线程情况下单例依旧唯一,但是懒汉模式每次调用getInstance 方法时由于synchronized 的存在,需要进行同步,造成不必要的资源开销。因此便有了下面双重锁模式的实现方式。

public class LazySingleton {
    private static LazySingleton mInstance = null;

    private LazySingleton() {

    }

    public static LazySingleton getInstance() {
        if (mInstance == null) {
            synchronized (LazySingleton.class) {
                if (mInstance == null) {
                    mInstance = new LazySingleton();
                }
            }
        }

        return mInstance;
    }
}

这样既避免了饿汉模式的缺点,又解决了懒汉模式的不足;确保单例只在第一次真正需要的时候创建。

Android 中的使用

在日常的Android开发中,也可以见到单例模式的身影。

    Glide.with(this).load(url).into(imageView);
    //Glide.with()
    public static RequestManager with(FragmentActivity activity) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(activity);
    }
   //RequestManagerRetriever.get()
     /** The singleton instance of RequestManagerRetriever. */
    private static final RequestManagerRetriever INSTANCE = new RequestManagerRetriever();
     /**
     * Retrieves and returns the RequestManagerRetriever singleton.
     */
    public static RequestManagerRetriever get() {
        return INSTANCE;
    }

可以看到,当我们写下Glide.with(..) 这行代码时,就完成了RequestManagerRetriever 这个类的实例化,这个类的单例模式是使用饿汉模式实现的。

    public static EventBus getDefault() {
        if (defaultInstance == null) {
            synchronized (EventBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
    };

很明显,EventBus的单例模式使用双重锁模式实现的。

    static InputMethodManager sInstance
    public static InputMethodManager getInstance() {
        synchronized (InputMethodManager.class) {
            if (sInstance == null) {
                IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
                IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
                sInstance = new InputMethodManager(service, Looper.getMainLooper());
            }
            return sInstance;
        }
    }

InputMethodManager 的单例模式是使用懒汉模式实现。

可以看到,关于单例模式的实现方式,面对不同的场景,我们可以做出不同的选择

由上可见,关于单例模式的实现,没有说哪一种方式最好,只有最合适的实现方式;实际开发中,单例模式应该怎么写,还需要根据业务场景做最合适的选择,无论是饿汉懒汉实用才是好汉。个人感觉,饿汉模式是一种简单又方便的实现方式, 一个类既然已经写成了单例模式,必然是要使用的呀,谁会去创建一个饿汉模式的单例,又不去使用这个单例呢?

之前在使用Volley的时候,就是使用饿汉模式创建整个应用的RequestQueue单例,所有需要网络请求的地方,把request添加到RequestQueue单例中即可。

public class MyApplication extends Application{
    // 建立请求队列
    public static RequestQueue queue;

    @Override
    public void onCreate() {
        super.onCreate();
        queue = Volley.newRequestQueue(getApplicationContext());
    }

    public static RequestQueue getHttpQueue() {
        return queue;
    }
}

在应用Application的onCreate方法中创建了属于整个应用的queue,之后每一次网络请求时,只需要queue.add(Request)即可,这里使用单例模式,可以有效的避免在多个地方创建RequestQueue 的实例,浪费系统资源。

更多

在某些复杂的场景中,上述的两种方式都或多或少的存在一些缺陷。因此便有了以下两种单例模式的实现方式。

静态内部类

public class StaticSingleton {
    private StaticSingleton(){

    }

    public static StaticSingleton getInstance(){
        return SingletonHolder.mInstance;
    }

    /**
     * 静态内部类
     */
    private static class SingletonHolder{
        private static final StaticSingleton mInstance=new StaticSingleton();
    }
}

可以说,这是最安全的实现方式了,无论怎样,这样产生的单例必然是单例。

枚举单例

public enum  EnumSingleton {
    INSTANCE;
}

定义一个枚举元素,而他就是单例;可以说,这是实现单例最简单最实惠的方式;可以有效的避免单例在反序列化的过程中被创建,从而让单例变得不唯一。但是,Google官方是不建议在Android开发中使用枚举的,所以使用具体使用哪种方式实现单例模式,仁者见仁智者见智了。

单例模式是设计模式中最简单的一种,因为他最容易理解;但通过上述分析可以看到,简单不意味着随意,针对不同的业务场景,需要我们仔细斟酌单例模式的实现方式


好了,关于单例模式就是这些了。

上一篇 下一篇

猜你喜欢

热点阅读