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

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源码设计模式》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值