设计模式之--单例模式

单例模式,他确保了一个类在指定时间内只有一个实例。这个实例充当一个共享资源的看门人或者作为一个中央通信枢纽。一个应用程序不能创建新的实例,所有的方法都通过改单一的实例来访问。应用程序通过这个类对外暴露的一个静态方法来调用改单例。

核心的系统功能通常使用单例模式来访问。例如,在Java中。java.lang.Runtime类就使用单例模式与应用程序的运行环境进行交互。

为什么单例模式由于使用一组静态方法?

1.继承与接口。 单例是对象,他可以基类继承并实现接口。

2.可能的多样性。 你可以改变你的想法,创建对个对象(例如一个线程一个)同时不需要修改大量的代码.。(当然,如果你这样做的话,那就不再是单例了)

3.动态绑定。 真正用来创建单例的类可以不再编译时决定,而在运行时决定。

单例模式并没有不足之处。由于在多线程环境中必须对该方法进行同步,所以减慢了对单例的访问。一个单例可能拖慢应用程序的启动时间,应为他需要初始化,并且可能会一直持有不再需要的资源。

问题:

你的应用程序使用一个日志类将调试信息写到控制台。怎样使用单例模式实现这个日志工具?

public class Logger {

	//单例模式要求任何时候最多只有一个日志类的实例。最简单的方法是将构造函数设为私有的,并在类中初始化一个实例。
	private static final Logger instance = new Logger();
	private Logger(){};
	public Logger getInstance(){
		return instance;
	}
	
	public void log(String msg){
		System.out.println(System.currentTimeMillis() + ":" + msg);
	}
}


问题:

你的应用程序使用了一个单例,但是并不是总是必须的,她的初始化开销很大,如何改进?

单例模式并没有指定对象实例在何时创建,只限制最多只有类的一个实例。类在加载的时候就创建实例不是必须的,只需要在之前创建即可。通过这种方式,如果getInstance应该在返回他之前没有初始化,则进行初始化。这个技巧称为延迟初始化或延迟加载。

public class Logger {

	private static Logger instance = null;
	private Logger(){};
	public static Logger getInstance(){
		if(instance == null){
			instance = new Logger();
		}
		return instance;
	}

	public void log(String msg){
		System.out.println(System.currentTimeMillis() + ":" + msg);
	}
}


这个简单的改变完成了初始化延迟,但是他不在是线程安全的。如果两个线程同时尝试着去调用创建getInstance(),这时就会发生问题。

可以添加synchronized关键字

public synchronized static Logger getInstance(){
		if(instance == null){
			instance = new Logger();
		}
		return instance;
	}
由于同步,这个改变需要付出巨大的性能代价,

java中的一个用法组合了延迟初始化和静态初始化,通过利用内部类的延迟加载,对实例进行静态初始化,这是线程安全的,因为类加载器保证是串行的,,无论多少线程同时调用getInstance,所以内部类只被加载和初始化一次,也避免了同步开销,因为串行化由类加载器保证--当类被加载后,就不再涉及类加载器,就没有剩余开销。可以将前面的getInstance通过如下替换来实现:

private static class LoggerHolder{
		public static final Logger instance = new Logger();
	}
public static Logger getInstance(){
		return LoggerHolder.instance;
}


--参考于《程序员面试攻略》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值