阅读笔记常见的设计模式之一:单例模式

来源:互联网 发布:c语言在线调试工具 编辑:程序博客网 时间:2024/05/22 06:05

1.介绍

应用最广的模式之一,单例对象的类必须保证只有一个实例存在,许多适合系统之需要拥有一个全局对象,这样有利于我们协调系统整体的行为。如在一个应用中,之需要存在一个ImaLoader,这个ImageLoader既含有线程池,缓存系统,网络请求,很耗费资源,因此没有理由让它构造多个实例。

2.定义

确保一个类只有一个实例,并且自行实例化向整个系统提供这个实例。
Ps:我觉得这两个点很重要,只有一个实例,怎么实现?private 构造函数;自行实例化:直接将类作为成员变量并且静态化。

几个关键点:
(1)构造函数私有化不对外开放,private声明
(2)通过一个静态方法或者枚举返回单例类对象
(3)确保单例类的对象只有一个,尤其是在多线程环境
(4)确保单例类在反序列化时候不会重新构建对象

3.使用场景

确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源,或者某个类型的对象应该有且只有一个。比如:访问IO和数据库,网络操作等

4.简单示例

public class Staff {public void work(){system.out.print("Staff");}}public class Vp extends Staff{public void work(){system.out.print("Vp");}}public class Ceo extends Staff(){//声明静态变量的时候就已经初始化了private static Ceo mCeo=new Ceo();private Ceo (){}public static Ceo getCeo(){return mCeo;}public void work(){system.out.print("Ceo");}}public class Company{private List(Satff) allStaffs=new Arraylist<Staff>();public void add(Staff per){allS0taffs.add(per);}public void showAllStaffs(){for(Staff per : allStaffs){system.out.print("Obi"+per.toString);}}}public class Test{public static void main(String[] args){Company company=new Company();Staff staff1=Ceo.getCeo();Staff staff2=Ceo.getCeo();company.add(staff1);company.add(staff2);company.showAllStaffs();}}

运行后发现两个Ceo对象是一样的,因为staff1和staff2完全一致。

5.其他实现方式

5.1 懒汉模式
前面是用饿汉模式实现的,它是声明静态变量的时候就已经初始化了。
懒汉模式是声明静态对象,只有在调用getInstance的时候进行初始化,而且在getInstance方法中添加了关键字synchronized,也就是getInstacne是一个同步方法,也就是保证在多线程情况下单例对象的唯一性。
如下:

public class Singleton(){private static Singonton mSingleton;private Singleton(){}public  static synchronized Singeoton getInstance(){if(mSingleton==null){mSingleton=new Singleton();}return mSingleton();}public void doSomething(){}}

存在的问题就是即使mSingleton已经被初始化了(第一次调用Singleton就会被初始化),每次调用getInstance的时候都要进行一次同步,这样会消耗不必要的资源。相对饿汉模式来说,优点是单例只有在使用时才会倍初始化。
5.2 DCL实现单例

public class Singleton{private static Singleton instance=null;private Singlrton(){}public static Singleton getInstance(){if(instance==null){synchronized(Singleton.class){if(instance==null){singleton=new Singleton();}}}return instance;}public void doSomething(){}}

本程序进行了两次判断第一次判断是为了不必要的同步,第二次判断是为了在null情况下创建实例。这种单例是使用最多的。

优点:资源利用率高,第一次执行getInstance才会被实例化。
缺点:第一次加载反应稍微慢点,高并发环境下有一定的缺陷,虽然概率小。

6.总结

优点:
(1)由于单例模式在内存中只有一个实例,减少了内存开支,特别是一个对象需要频繁的创建和销毁时。
(2)单例模式可避免对资源的多重占用,例如一个写文件操作,由于只有一个实例存在内存中,所以避免对同一个文件同时写操作。
缺点:
(1)没有接口,很难扩展,扩展只有修改代码
(2)单例对象如果持有context,很容易发生内存泄露,因为如果该context是某个activity持有的化,当该activity被销毁时,对应的context也被销毁,造成内存泄露,解决办法是,传递给单例对象的context最好是Application Context。

感谢《android源码设计模式》

原创粉丝点击