单例模式

 自以为拥有财富的人,其实是被财富所拥有。


本讲内容:单例模式


一、单例模式Singleton

1、应用场合:有些对象只需要一个就足够了,如古代皇帝,如配置文件、工具类、线程池、缓存、日志对象等

2、作用:保证整个应用程序中某个实例有且只有一个(如果创造出多个实例,就会导致很多问题,占用资源过多,不一致的结果等)

3、类型:饿汉模式和懒汉模式

区别:

饿汉模式的特点是加载类时比较慢,但运行时获取对象的速度比较快,线程安全
懒汉模式的特点是加载类时比较快,但运行时获取对象的速度比较慢,线程不安全

示例一:

/**
 * 饿汉模式:随着类的加载就创建了唯一的实例
 */
public class Singleton {
	//1.将构造方法私有化,不允许外部直接创建对象
	private Singleton(){
		
	}
	
	//2.创建类的唯一实例,使用private static修饰
	private static Singleton instance=new Singleton();
	
	//3.提供一个用于获取实例的方法,使用public static修饰
	public static Singleton getInstance(){
		return instance;
	}
}


/**
 * 懒汉模式:只有第一次调用共有方法时才创建唯一的实例
 */
public class Singleton2 {
	//1.将构造方式私有化,不允许外边直接创建对象
	public Singleton2() {
	}
	
	//2.声明类的唯一实例,使用private static修饰
	private static Singleton2 instance;
	
	//3.提供一个用于获取实例的方法,使用public static修饰
	public static Singleton2 getInstance(){
		if(instance==null){
			instance=new Singleton2();
		}
		return instance;
	}
}

懒汉模式是线程不安全的,如果现在有两个线程同时在执行getInstance方法,第一个线程刚执行完第14行,还没执行第15行,这个时候第二个线程执行到了第14行,它会发现sLogUtil还是null,于是进入到了if判断里面。这样你的单例模式就失败了,因为创建了两个不同的实例。也可以通过双重锁定方法解决

public static Singleton2 getInstance(){
	if(instance==null){
		synchronized(Singleton2.class){
			if(instance==null){
				instance=new Singleton2();
			}
		}
	}
	return instance;
}


public synchronized static Singleton2 getInstance(){
		if(instance==null){
					instance=new Singleton2();
		}
		return instance;
	}


/**
 *测试类
 */
public class test {
	public static void main(String[] args) {
		//饿汉模式
		Singleton s1=Singleton.getInstance();
		Singleton s2=Singleton.getInstance();
		if(s1==s2){
			System.out.println("s1和s2是同一个实例");
		}else{
			System.out.println("s1和s2不是同一个实例");
		}
		
		// 懒汉模式
		Singleton2 s3 = Singleton2.getInstance();
		Singleton2 s4=Singleton2.getInstance();
		if(s3==s4){
			System.out.println("s3和s4是同一个实例");
		}else{
			System.out.println("S3和s4不是同一个实例");
		}
		
	}
}

打印:

s1和s2是同一个实例
s3和s4是同一个实例


示例二:一个能够控制打印级别的日志工具类

public class LogUtil {
	private static final int VERBOSE = 1;
	private static final int DEBUG = 2;
	private static final int INFO = 3;
	private static final int WARN = 4;
	private static final int ERROR = 5;
	private static final int NOTHING = 6;

	private static final int LEVEL = VERBOSE;

	private static LogUtil instance = new LogUtil();

	private LogUtil() {
	}

	public static LogUtil getInstance() {
		return instance;
	}

	public static void v(String tag, String msg) {
		if (VERBOSE >= LEVEL) {
			Log.v(tag, msg);
		}
	}

	public static void d(String tag, String msg) {
		if (DEBUG >= LEVEL) {
			Log.d(tag, msg);
		}
	}

	public static void i(String tag, String msg) {
		if (INFO>= LEVEL) {
			Log.i(tag, msg);
		}
	}

	public static void w(String tag, String msg) {
		if (WARN >= LEVEL) {
			Log.w(tag, msg);
		}
	}

	public static void e(String tag, String msg) {
		if (ERROR >= LEVEL) {
			Log.e(tag, msg);
		}
	}
}

通过这个类来打印日志,只需要控制level的级别,就可以自由地控制打印的内容。比如现在项目处于开发阶段,就将level设置为DEBUG,这样所有的日志信息都会被打印。而项目如果上线了,可以把level设置为INFO,这样就只能看到INFO及以上级别的日志打印。如果你只想看到错误日志,就可以把level设置为ERROR。而如果你开发的项目是客户端版本,不想让任何日志打印出来,可以将level设置为NOTHING(项目上线时)。打印的时候只需要调用:

LogUtil.getInstance().d("TAG","debug log");  






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值