题外话:
近期由于新型病毒疫情比较严重,本着珍爱生命的原则,我也只能窝在家里自我隔离,但又不想浪费这大好时光,就想着一直以来就对android中常见的设计模式一知半解,正好趁现在边复习边学习,顺便记录下来,希望对以后的自己有所帮助。最后小小的祈祷下疫情赶快过去,武汉加油,中国加油!
简介:
什么是设计模式?
设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。说白了其实就是行业大佬总结出来的被简化过后可重复利用的代码或者说是代码习惯,然后被多数人公认,依葫芦画瓢所使用,从而达到代码的可靠和可读性。
为什么学习设计模式?
1、首先它是一种被公认的知识,是个人能力提升的捷径,也是大多数面试会涉及到的知识点。
2、它是大多数代码中所运用的,学习它能提高代码的阅读能力,也避免了重复造轮子。
单例模式:
单例模式是最简单的设计模式之一。这种类型的设计模式属于创造型模式,它提供了一种创造对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
说白了就是当整个应用内存中不存在这个对象时,我们可以通过调用这个类对外提供的方法来创建这个对象,一旦这个对象被创建过并且没有被系统回收,那么我们此时调用此方法不创建对象,而是直接获取内存中的对象的引用。保证了整个应用中有且只有一个该对象。
Android中的使用:
懒汉式,线程不安全
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这种方式是利用静态变量非空判断实现延时初始化,但却没有对静态方法加锁synchronized,这就导致了一个问题,在多线程的程序中没法保证单例,所以是线程不安全的。于是就有了下面这种线程安全的懒汉式单例。
懒汉式、线程安全
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这种方式只是在上一种的静态方法上添加了同步锁synchronized,从而保证了在多线程中也能正常使用。但由于对类进行了同步锁,导致了效率低下,因为大多数情况下是不需要同步的。为了提高效率又保证线程安全又演化出下面这种方式。
饿汉式
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
这种方式利用类加载时就初始化单例对象,当多个线程调用getInstance()获取对象时只是获取早已存在于内存中的对象的引用,从而保证了多线程的安全性。但是这种方式在类加载时初始化,也许某一段程序中根本用不到这个对象,浪费内存,导致内存泄漏。
double-checked locking(双重校验锁)
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
这是种常用的单例模式,利用volatile保证Singleton变量的可见性。然后利用双重非空检查和对Singleton.class类的同步锁实现了多线程安全的单例,又保证了延时初始化,同时还保证了高效性。
静态内部类
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
这种方式是饿汉式的延伸,它虽然也是利用classloader原理,但却利用静态内部类实现了延时初始化,只有通过显示调用了getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。
枚举
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
枚举是一种没有被广泛运用的实现单例的方法,它更加简洁、支持序列化机制并且绝对防止多次实例化,而且还能防止反序列化重新创建新的对象。因此如果涉及到反序列化创建对象时,可以尝试使用。