Android 单例模式

1、单例模式介绍

据说在一个app 中,单例对象的类必须保证只有一个实例存在,系统只有一个全局变量存在。

2、单例模式的简单例子

假设一个公司在 只能有一个CEO ,可以有多个经理,员工。那么我们就把CEO 设为单例模式,并且在不同位置实例化,看看是不是一个实例。

package com.example.menglux.simplesingle;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        Company cp = new Company();

        //CEO 对象只能通过getCeo 函数获取
        Staff ceo1 = CEO.getCeo();
        Staff ceo2 = CEO.getCeo();

        //添加 CEO 实例进列表
        cp.addStaff(ceo1);
        cp.addStaff(ceo2);

        //通过 new 创建 VP 对象
        Staff VP1 = new VP();
        Staff VP2 = new VP();

        //通过new 创建Staff 对象
        Staff Staff1 = new Staff();
        Staff  Staff2 = new Staff();
        Staff Staff3 = new Staff();



        //添加 经理 员工 实例对象 进列表
        cp.addStaff(VP1);
        cp.addStaff(VP2);
        cp.addStaff(Staff1);
        cp.addStaff(Staff2);
        cp.addStaff(Staff3);


        //显示列表里面的类
        cp.showAllStaffs();
    }

    //公S司类
    public class Company {
        private List<Staff> allStaffs = new ArrayList<Staff>();    //创建一个列表,用来保存,类

        public void addStaff(Staff per) {     //向列表添类 实例化对象
            allStaffs.add(per);
        }

        public void showAllStaffs() {      //将列表的类都显示出来
            for (Staff per : allStaffs) {
                System.out.println("Obj: " + per.toString());
            }
        }
    }



    //普通员工的类
    public static class Staff {
        public void work(){
            //do something
        }
    }


    //经理的类
    public class VP extends  Staff {
        @Override
        public void work(){
            //do something
        }
    }



    //CEO 的 类
    public static class CEO extends  Staff {
        private static final  CEO mceo = new CEO(); //引用私有构造方法

        private CEO () {

        }

        public static  CEO getCeo () {
            return mceo;
        }

        @Override
        public void work(){
            //do something
        }
    }
}

我们运行一下 可以看到答应你出来的log:

09-20 13:47:01.039 8961-8961/com.example.menglux.simplesingle I/System.out: Obj: com.example.menglux.simplesingle.MainActivity$CEO@43789518
09-20 13:47:01.039 8961-8961/com.example.menglux.simplesingle I/System.out: Obj: com.example.menglux.simplesingle.MainActivity$CEO@43789518


09-20 13:47:01.039 8961-8961/com.example.menglux.simplesingle I/System.out: Obj: com.example.menglux.simplesingle.MainActivity$VP@43789840
09-20 13:47:01.039 8961-8961/com.example.menglux.simplesingle I/System.out: Obj: com.example.menglux.simplesingle.MainActivity$VP@43789850

09-20 13:47:01.039 8961-8961/com.example.menglux.simplesingle I/System.out: Obj: com.example.menglux.simplesingle.MainActivity$Staff@43789860
09-20 13:47:01.039 8961-8961/com.example.menglux.simplesingle I/System.out: Obj: com.example.menglux.simplesingle.MainActivity$Staff@43789870
09-20 13:47:01.039 8961-8961/com.example.menglux.simplesingle I/System.out: Obj: com.example.menglux.simplesingle.MainActivity$Staff@43789880

其中添加的两个 CEO 实例是两个一样的数据。也就是说两个实例是同一个。

上面代码我们可以知道,CEO 类不能通过 new 的形式来构造对象,只能通过 CEO.getCeo() 的函数来获取,而这个CEO 对象是静态对象,并且在声明的时候已经初始化,这就保证了
CEO 对象的唯一性。

3、懒汉模式实现单例模式

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

getInstance() 方法里添加了synchronized 关键字,也就是 getInstance 是一个同步方法,这就保证多线程情况下单例的唯一性。
优点:单例只有在使用时才被实例化
缺点:每次调用 getInstance 都进行同步,造成不必要的同步开销。

4、Double Check Lock (DLC) 实现单例

    public static class Singleton {
        private static Singleton sinstance;

        private Singleton() {
        }

        public void doSomething() {
            //dosomething
        }

        private static Singleton getInstance() {
            if (sinstance == null) {
                synchronized (Singleton.class) {
                    if (sinstance == null) {
                        sinstance = new Singleton();
                    }
                }
            }
            return sinstance;
        }
    }

优点:资源利用率高
缺点:第一次加载慢,在高并发的状态下会出现小概率 缺陷

5、静态内部类单例模式

 public static class Singletion {
        private Singletion() {
            
        }
        
        public  static Singleton getInstance() {
            return SingletonHolder.sInstance;
        }
        
        
        /*静态内部类*/
        private static class SingletonHolder {
            private static final Singleton sInstance = new Singleton();
        }
    }

1)第一次加载Singletion 类时不会初始化sInstance,只有在第一次调用Singleton的 getInstance方法时才会导致sInstance被初始化。
2)不仅保障线程安全,而且还是能够保证单例对象的唯一性。

6、枚举单例

    public enum SingletonEnum {
        INSTANCE;
        public void doSomething() {
            //dosomething
        }
    }

1)写法简单
2)系统默认 线程安全

具体怎么使用 没深入研究

7、使用容器是实现单例模式

这里只是把 创建的单一的实体类对象,放到hash 表里面。

    public static class SingletonManager {
        private static Map<String, Object> objMap = new HashMap<String, Object>();
        
        private SingletonManager() {}
        
        public static void registerService(String key, Object instance) {
            if (!objMap.containsKey(key)) {
                objMap.put(key,instance);
            }
        }
        
        public static Object getService (String key) {
            return objMap.get(key);
        }
    }

文献参考:
Android 源码设计模式解析与实战 第二版

本人郑重声明,本博客所编文章、图片版权归权利人持有,本博只做学习交流分享所用,不做任何商业用途。访问者可將本博提供的內容或服务用于个人学习、研究或欣赏,不得用于商业使用。同時,访问者应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人的合法权利;如果用于商业用途,须征得相关权利人的书面授权。若文章、图片的原作者不愿意在此展示內容,请及时通知在下,將及时予以刪除。

猜你喜欢

转载自blog.csdn.net/qq_27061049/article/details/82787191