刚开始做项目的时候,并不太关注设计模式的运用,现在回头看看,发现代码的质量不忍直视,当初在写的时候心里觉得很多地方是可以优化的, 奈何当时并不懂如何优化是好,后来仔细的去学了一下Android设计模式(何红辉、关爱民所著),受益匪浅,特做几篇笔记以做记录。不当之处敬请指出。
现在回头看看项目,发现很多地方代码质量可以得到很大程度的提升,代码不能只实现产品经理所需要的功能,还必须多考虑代码如何优化如何扩展,在需求经常变动的时候,如何使代码可以轻易的跟随需求而变动,同时也方便别人的阅读。
下面来讲解一下低头不见抬头见的的单例模式,单例模式主要用于某个类创建过多对象会造成在资源浪费的问题,例如图片网络访问框架、文件数据库读取框架等。
单例模式指的是一个类只有一个实例,在内部实例化,将实例对象返回给调用者,单例模式都有个特点,构造函数私有化,保证调用者只能通过调用该类公开的方法来获取实例对象。常见的单例模式有几种:饿汉模式、懒汉模式、 Double CheckLock(DCL)模式、静态内部类单例模式
饿汉模式【饿汉模式是在声明静态单例对象时即初始化该实例】
/**饿汉模式*/ public class InstanceModel { /**声明静态对象时期初始化*/ private static final InstanceModel instance=new InstanceModel(); /**构造函数私有化,防止调用者创建新的对象*/ private InstanceModel(){} public static InstanceModel getInstance(){ return instance; } }
懒汉模式【懒汉模式是在调用者第一次调用时初始化】
/**懒汉模式*/ public class InstanceModel { private static InstanceModel instance; private InstanceModel(){} /**在调用者调用的时候才会进行初始化,加了synchronized主要是确保在多线程下单例对象唯一*/ public static synchronized InstanceModel getInstance(){ if(instance==null){ instance=new InstanceModel(); } return instance; } }
两者对比:
饿汉模式在编译时期即进行初始化,可能会导致编译时间略长,而懒汉模式是在调用时才进行初始化,编译较快,但是每次获取实例对象时都会进行同步操作,造成不必要的资源开销,一般不太建议使用。
Double CheckLock(DCL)模式
DCL模式一方面可以避免饿汉模式在编译器就进行初始化导致编译较慢的问题,一方面又能解决懒汉模式因为同步锁造成的资开销问题,我一般较常选择这个模式。
/**DCL模式*/ public class InstanceModel { private static InstanceModel instanceModel=null; private InstanceModel(){} /** * 可以看到此处进行了两次instanceModel是否为空的判断 * 第一个判断当然是为了不必要的同步,类似于懒汉模式 */ public static InstanceModel getInstance(){ if(instanceModel==null){ synchronized (InstanceModel.class){ /** * 这里为何还要再进行第二次判断呢? * 因为在执行instanceModel=new InstanceModel()的时候,这句代码编译成多条编译指令 * 主要执行三件事: * 1.给InstanceModel分配内存 * 2.调用InstanceModel的构造函数初始化成员字段 * 3.将instanceModel指向分配的内存空间. * 但是这三条指令并非顺序执行,如果先执行了3,2未执行,此时被切换到其他线程上去,其他线程获取了instance,使用就会出错。(JDK1.5前) * JDK之后将instanceModel的定义改成 * private volatile static InstanceModel instanceModel=null;即可,保证对象都是从主内存中获取。 * */ if(instanceModel==null){ instanceModel=new InstanceModel(); } } } return instanceModel; } }
静态内部类的单例模式
/**静态内部类单例模式*/ public class InstanceModel { private InstanceModel(){} public static InstanceModel getInstance(){ return InnerInstanceModel.intance; } /**第一次加载Instancemodel类不会初始化instance,只有第一次调用getInstance()方法才会导致instance初始化*/ private static class InnerInstanceModel{ private static final InstanceModel intance=new InstanceModel(); } }
在Android中如果静态单例持有了activity的引用,可能会造成内存泄漏,这是个很值得注意的问题。