美文网首页
大话设计模式-单例模式-2020-10-23

大话设计模式-单例模式-2020-10-23

作者: 勇往直前888 | 来源:发表于2020-10-23 17:21 被阅读0次

定义

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

结构图

image.png

使用场景

  • 通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。

  • 单例模式因为Singleton类封装它的唯一实例,这样它可以严格地控制客户怎样访问它以及何时访问它。简单地说就是对唯一实例的受控访问。

  • 让构造方法private,就堵死了外界利用new创建此类实例的可能。

  • 多线程时,要注意同时访问getInstance()方法,导致创建多个实例的可能性。

单例多种写法的例子

  1. 懒汉模式,同步操作防止多线程创建多个对象。
/**
 * 懒汉模式的单例,线程安全
 */

class LazySingleton {
    // 私有化构造函数,防止new对象
    private LazySingleton() {}

    private static LazySingleton instance;

    // 同步方式保证线程安全,但是效率比较低下
    public static synchronized LazySingleton getInstance() {
        if (null == instance) {
            instance = new LazySingleton();
        }
        return instance;
    }
}
  • 在第一次被引用时,才会将自己实力化,所以就被称为懒汉式单例类。
  1. 饿汉式单例类Eager Singleton;Android Studio的单例模板就是用这个来做的。
/**
 * 饿汉式单例类
 */
class EagerSingleton {
    //类加载时就初始化
    private static final EagerSingleton ourInstance = new EagerSingleton();

    static EagerSingleton getInstance() {
        return ourInstance;
    }

    // 防止new操作
    private EagerSingleton() {
    }
}
  • 这种静态初始化的方式是在自己被加载时就将自己实例化,所以被称之为饿汉式单例类。

  • 饿汉式的创建方式在一些场景中将无法使用:譬如 Singleton 实例的创建是依赖参数或者配置文件的,在 getInstance() 之前必须调用某个方法设置参数给它,那样这种单例写法就无法使用了。

  1. 双重检验锁
/**
 * 双重检验锁方式的单例类
 */
class DoubleCheckSingleton {
    // 定义单例静态变量
    private volatile static DoubleCheckSingleton instance = null;

    // 构造函数私有化
    private DoubleCheckSingleton() {}

    // 获取单例对象方法
    public static DoubleCheckSingleton getInstance() {
        if (instance == null) {
            synchronized (DoubleCheckSingleton.class) {
                if (instance == null) {
                    instance = new DoubleCheckSingleton();
                }
            }
        }
        return instance;
    }
}
  • 第1层检验没有synchronized,是异步的,效率较高。第2层检验是synchronized,保证多线程安全

  • 实例用volatile修饰。使用 volatile 的主要原因是:禁止指令重排序优化。也就是说,在 volatile 变量的赋值操作后面会有一个内存屏障(生成的汇编代码上),读操作不会被重排序到内存屏障之前。

  1. 静态内部类方式
/**
 * 静态内部类方式单例
 */
class StaticNestedClassSingleton {
    private static class SingletonHolder {
        private static final StaticNestedClassSingleton INSTANCE = new StaticNestedClassSingleton();
    }
    private StaticNestedClassSingleton (){}
    public static final StaticNestedClassSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
image.png
  • 客户端代码
public class SingletonActivity extends AppCompatActivity {

    public static void launch(Context context) {
        if (null != context) {
            Intent intent = new Intent();
            intent.setClass(context, SingletonActivity.class);
            if (!(context instanceof Activity)) {
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            }
            context.startActivity(intent);
        }
    }

    TextView checkTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_singleton);
        setTitle("单例模式");

        checkTextView = findViewById(R.id.textViewCheck);
    }

    public void onLazyButtonClick(View view) {
        LazySingleton lazySingleton1 = LazySingleton.getInstance();
        LazySingleton lazySingleton2 = LazySingleton.getInstance();
        checkSingleton(lazySingleton1, lazySingleton2);
    }

    public void onEagerButtonClick(View view) {
        EagerSingleton eagerSingleton1 = EagerSingleton.getInstance();
        EagerSingleton eagerSingleton2 = EagerSingleton.getInstance();
        checkSingleton(eagerSingleton1, eagerSingleton2);
    }

    public void onDoubleCheckButtonClick(View view) {
        DoubleCheckSingleton doubleCheckSingleton1 = DoubleCheckSingleton.getInstance();
        DoubleCheckSingleton doubleCheckSingleton2 = DoubleCheckSingleton.getInstance();
        checkSingleton(doubleCheckSingleton1, doubleCheckSingleton2);
    }

    public void onNestedClassButtonClick(View view) {
        StaticNestedClassSingleton staticNestedClassSingleton1 = StaticNestedClassSingleton.getInstance();
        StaticNestedClassSingleton staticNestedClassSingleton2 = StaticNestedClassSingleton.getInstance();
        checkSingleton(staticNestedClassSingleton1, staticNestedClassSingleton2);
    }

    private void checkSingleton(Object object1, Object object2) {
        String message = "";
        if (object1 == object2) {
            message = "对象object1:" + object1 + "\n"
                    + "对象object2:" + object2 + "\n"
                    + "是相同的实例";
        } else {
            message = "对象object1:" + object1 + "\n"
                    + "对象object2:" + object2 + "\n"
                    + "是不同的实例";
        }
        checkTextView.setText(message);
    }
}

Demo地址

https://gitee.com/zhangxusong888/Android/tree/master/design_pattern

相关文章

  • 大话设计模式之_单例模式

    大话设计模式之___单例模式 什么是单例模式单例模式有哪些(会顺带讲些懒汉式的性能优化)懒汉式与饿汉式的区别 什么...

  • 单例模式Java篇

    单例设计模式- 饿汉式 单例设计模式 - 懒汉式 单例设计模式 - 懒汉式 - 多线程并发 单例设计模式 - 懒汉...

  • 大话设计模式-单例模式-2020-10-23

    定义 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 结构图 使用场景 通常我们可以让一个全局变量使得一个...

  • python中OOP的单例

    目录 单例设计模式 __new__ 方法 Python 中的单例 01. 单例设计模式 设计模式设计模式 是 前人...

  • 单例

    目标 单例设计模式 __new__ 方法 Python 中的单例 01. 单例设计模式 设计模式设计模式 是 前人...

  • 设计模式 - 单例模式

    设计模式 - 单例模式 什么是单例模式 单例模式属于创建型模式,是设计模式中比较简单的模式。在单例模式中,单一的类...

  • 设计模式

    常用的设计模式有,单例设计模式、观察者设计模式、工厂设计模式、装饰设计模式、代理设计模式,模板设计模式等等。 单例...

  • 2018-04-08php实战设计模式

    一、单例模式 单例模式是最经典的设计模式之一,到底什么是单例?单例模式适用场景是什么?单例模式如何设计?php中单...

  • python 单例

    仅用学习参考 目标 单例设计模式 __new__ 方法 Python 中的单例 01. 单例设计模式 设计模式设计...

  • 基础设计模式:单例模式+工厂模式+注册树模式

    基础设计模式:单例模式+工厂模式+注册树模式 单例模式: 通过提供自身共享实例的访问,单例设计模式用于限制特定对象...

网友评论

      本文标题:大话设计模式-单例模式-2020-10-23

      本文链接:https://www.haomeiwen.com/subject/anhvmktx.html