据说在一个app 中,单例对象的类必须保证只有一个实例存在,系统只有一个全局变量存在。
假设一个公司在 只能有一个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 allStaffs = new ArrayList(); //创建一个列表,用来保存,类
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 对象的唯一性。
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 都进行同步,造成不必要的同步开销。
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;
}
}
优点:资源利用率高
缺点:第一次加载慢,在高并发的状态下会出现小概率 缺陷
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)不仅保障线程安全,而且还是能够保证单例对象的唯一性。
public enum SingletonEnum {
INSTANCE;
public void doSomething() {
//dosomething
}
}
1)写法简单
2)系统默认 线程安全
具体怎么使用 没深入研究
这里只是把 创建的单一的实体类对象,放到hash 表里面。
public static class SingletonManager {
private static Map objMap = new HashMap();
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 源码设计模式解析与实战 第二版
本人郑重声明,本博客所编文章、图片版权归权利人持有,本博只做学习交流分享所用,不做任何商业用途。访问者可將本博提供的內容或服务用于个人学习、研究或欣赏,不得用于商业使用。同時,访问者应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人的合法权利;如果用于商业用途,须征得相关权利人的书面授权。若文章、图片的原作者不愿意在此展示內容,请及时通知在下,將及时予以刪除。