重温单例模式

前两天面试被问到设计模式了,感觉答的不好,在复习下。

所谓单例模式,简单的说就是保证一个类只有一个实例对象,并提供一个全局的访问点来获取它。

知道了单例模式的定义,那么怎么实现呢?从定义上看,必须先保证类只用一个实例,我们都知道要取得一个类的实例直接通过调用类的构造方法来获取,构造方法一般是public的,所以我们可以从类外部多次调用它来获取类的实例,那么现在就要限制类外部不能调用它,即它对外部是不可见的,透明的,我们可以使用private来修饰它,即构造方法私有化。让类自己来控制其自身对象的创建。现在就可以由类本身来控制创建实例的个数。那么另一个问题就是类外部要获取这个类的实例,我们可以提供一个方法,但是普通的方法,又要通过类的实例去获取,所以不能用其一般的方法,现在我们想到了静态方法,直接由类名去调用,那么现在就解决了类只用一个对象和全局访问点的问题。

如何实现单例模式呢,实现单例模式有两种方式,一种是懒汉式,另一种是饿汉式。下面具体来看代码。

懒汉式实现:

package com.zcl.singleton;

/**
 * 懒汉式单列模式
 * @author Administrator
 *
 */

public class Singleton {
	//定义一个变量存储创建好的类的实例
	private static Singleton instance = null ;
	
	private Singleton(){
		//
	}
	
	/**
	 * 定义一个方法供外部调用取得实例
	 * @return 一个Singleton实例
	 */
	public static Singleton getInstance(){
		if(instance==null){
			instance = new Singleton() ;
		}
		return instance ;
	}
}


饿汉式实现:

package com.zcl.singletonB;

/**
 * 饿汉式
 * @author Administrator
 *
 */
public class Singleton {
	private static Singleton instance = new Singleton() ;
	
	private Singleton(){
		//
	}
	
	public static Singleton getInstance(){
		return instance ;
	}
}

从两种实现方式对比来看,其实很明显,懒汉式就是需要的时候创建类的实例(这是延迟加载的思想)。而饿汉式是当java虚拟机加载该类的字节码时就实例化了一个类的对象,不管你以后要用不用。所以两种实现各有优缺点。懒汉式是体现了时间换空间的思想(每次判断要花费大量的时间),而饿汉式则是一种空间换时间的思想(即使没用到也创建了,以后要用就不要判断是否创建了)。还有一点就是懒汉式实现方式是线程不安全的,而饿汉式则是线程安全的。


下面讲讲解决线程不安全的方式,最直接的方式就是给方法加上同步锁,但是这样的话每次都要判断,降低访问速度。还有另一种方式就是使用“双重检查加锁”,也就是将同步等进到方法里面检查方法没创建后在进行。

示例代码:

package com.zcl.singleton;

/**
 * 懒汉式单列模式
 * @author Administrator
 *
 */

public class Singleton {
	//定义一个变量存储创建好的类的实例
	private static Singleton instance = null ;
	
	private Singleton(){
		//
	}
	
	/**
	 * 定义一个方法供外部调用取得实例
	 * @return 一个Singleton实例
	 */
	public static Singleton getInstance(){
		if(instance==null){
			synchronized (Singleton.class) {
				if(instance==null){
					instance = new Singleton() ;
				}
			}
		}
		return instance ;
	}
}

那么我们现在还要解决饿汉式的资源浪费怎么办呢,可不可以即解决资源浪费,有同时实现延迟加载呢?答案是肯定的,我们可以同个使用java的类级内部类和多线程缺省同步知识来解决。

示例代码:

package com.zcl.singleton;

/**
 * 使用类级内部类和缺省线程同步实现单例模式
 * @author Administrator
 *
 */
public class SingletonSyn {
	/**
	 * 类级内部类 ,定义一个用于保存对象实例的属性
	 */
	private static class SingletonHolder{
		private static SingletonSyn instance = new SingletonSyn() ;
	}
	
	private SingletonSyn(){
		//
	}
	
	public static SingletonSyn getInstance(){
		return SingletonHolder.instance ;
	}
}

还有一种高效的方法是使用枚举。这里就不介绍了。


总结下:

单例模式定义:保证一个类只有一个实例,并提供一个全局访问点供外部调用。

应用要求:1.当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。

    2.当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时

使用场景:读取配置文件,缓存系统设计,window任务管理系统等




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值