Android 设计模式之单例模式

该原创文章首发于微信公众号:字节流动

设计模式

设计模式简而言之就是优秀的代码设计经验的总结。设计模式的产生是为了提高代码的可复用性,可扩展性以及可靠性,但是往往会降低可读性。

设计模式原则

  • 单一职责原则: 一个类只负责一项职责;
  • 里氏替换原则: 子类可以扩展父类的功能,但不能改变父类原有的功能;
  • 依赖倒置原则: 面向接口编程,将依赖对象的共同特征抽象成接口;
  • 接口隔离原则: 一个类不应该实现它不需要的接口方法,即建立单一接口,细化接口,尽量减少接口中的方法;
  • 迪米特法则: 一个对象应该对其他对象保持最少的了解,即降低类与类之间的耦合;
  • 开闭原则: 一个类对扩展开放,对修改关闭。

设计模式分类

创建型设计模式

设计对象的实例化,避免用户用 new 运算符创建对象。例如单例模式,Builder 模式,原型模式等。

行为型设计模式

设计对象之间的通信交互。如观察者模式,迭代器模式,责任链模式等。

结构型设计模式

设计如何组合类和对象以形成更大的结构。如适配器模式,代理模式,桥接模式等。

单例模式

简单介绍常用的五种单例模式的写法。

饿汉式单例

public class Person {

    private static final Person INSTANCE = new Person();

    private Person(){

    }

    public static Person getInstance() {
      return INSTANCE;
    }
}

优点:线程安全。
缺点:类加载的时候就进行初始化,对于初始化逻辑复杂的类,会导致类加载变慢。

(DCL) 懒汉式单例

public class Person {
    private static volatile Person sInstance = null;

    private Person(){
    }

    public static Person getInstance() {
        if (sInstance == null){
            synchronized (Person.class) {
                if (sInstance == null) {
                    sInstance = new Person();
                  
                }
            }
        }

        return sInstance;
    }
}

优点:volatile 声明单例引用,可以防止并发时初始化成员变量和对象实例化顺序可能会被打乱,双重检查锁定解决了多余的同步问题。
缺点:JVM 创建一个对象会执行 3 个原子操作,在高并发时仍存在极小的概率导致 DCL 失效。

静态内部类单例

public class Person {

    private Person(){
    }

    private static class Singleton {
        private static final Person INSTANCE = new Person();
    }

    public static Person getInstance() {
        return Singleton.INSTANCE;
    }
}

优点:充分结合了懒汉式单例与饿汉式的优点,同时有效避开了它们的缺点,充分保证线程安全。推荐
缺点:会有的!

枚举型单例

public enum PersonEnum {
    INSTANCE;

    private PersonEnum() {
      
    }

    public void fun() {
         // do something
    }
}

使用方法:

PersonEnum.INSTANCE.fun();

优点:简洁,线程安全。
《Effective Java》的作者在书中是这样夸枚举型单例:

这种写法在功能上与共有域方法相近,但是它更简洁,无偿地提供了序列化机制,绝对防止对此实例化,即使是在面对复杂的序列化或者反射攻击的时候。
虽然这中方法还没有广泛采用,但是单元素的枚举类型已经成为实现Singleton的最佳方法。

缺点:Google 官方强烈建议尽量不要使用 enum ,它会增加额外的内存占用,同时增加可执行文件 .dex 的大小,也不适用继承场景。

容器型单例

public class Person {

    public Person () {
    }
}

public class SingletonManager {

    public static final KEY_SINGLETON = "singleton";

    private static Map<String, Object> sInstanceMap = new HashMap<>();

    public static void registerSingleton(String key, Object obj) { 
        if (!sInstanceMap.containsKey(key)) {
            sInstanceMap.put(key, obj);     
        }
    }

    public static Person getSingleton(String key) {
        return (Person) sInstanceMap.get(key);   
    }
}

使用:

SingletonManager.registerSingleton(KEY_SINGLETON, new Person);
Person person = SingletonManager.getSingleton();

优点:可以将不同单例注册到一个容器中统一管理,隐藏了类的具体实现,降低了耦合度。推荐
缺点:会有的!

单例模式的优点与缺点

优点:减少内存开销,避免资源重用。
缺点:单例类的扩展性很差,持有外部引用时,非常容易造成内存泄漏。

联系与交流

我的公众号
在这里插入图片描述
我的微信
在这里插入图片描述

发布了53 篇原创文章 · 获赞 18 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/Kennethdroid/article/details/102083324
今日推荐