为什么单例
1、在内存中只有一个对象,节省内存空间。避免频繁的创建销毁对象,可以提高性能。避免对共享资源的多重占用。可以全局访问。
2、确保一个类只有一个实例,自行实例化并向系统提供这个实例
单例需要注意的问题
1、线程安全问题
2、资源使用问题
单件模式用途:
单件模式属于工厂模式的特例,只是它不需要输入参数并且始终返回同一对象的引用。
单件模式能够保证某一类型对象在系统中的唯一性,即某类在系统中只有一个实例。它的用途十分广泛,打个比方,我们开发了一个简单的留言板,用户的每一次留言都要将留言信息写入到数据库中,最直观的方法是没次写入都建立一个数据库的链接。这是个简单的方法,在不考虑并发的时候这也是个不错的选择。但实际上,一个网站是并发的,并且有可能是存在大量并发操作的。如果我们对每次写入都创建一个数据库连接,那么很容易的系统会出现瓶颈,系统的精力将会很多的放在维护链接上而非直接查询操作上。这显然是不可取的。
如果我们能够保证系统中自始至终只有唯一一个数据库连接对象,显然我们会节省很多内存开销和cpu利用率。这就是单件模式的用途。当然单件模式不仅仅只用于这样的情况。在《设计模式:可复用面向对象软件的基础》一书中对单件模式的适用性有如下描述:
1、当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
2、当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
下面对单件模式的懒汉式与饿汉式进行简单介绍:
1、饿汉式:在程序启动或单件模式类被加载的时候,单件模式实例就已经被创建。
2、懒汉式:当程序第一次访问单件模式实例时才进行创建。
如何选择:如果单件模式实例在系统中经常会被用到,饿汉式是一个不错的选择。
反之如果单件模式在系统中会很少用到或者几乎不会用到,那么懒汉式是一个不错的选择。
饿汉式Demo1
/**
*
* @author sprin
* 饿汉式
* 直接创建实例对象,不管你是否需要这个对象都会创建
*
* 1.构造器私有化
* 2.自行创建,并用静态变量保存
* 3.向外提供这个实例
* 4.强调这是一个单例,我们可以用final修饰
*
*/
public class Singleton1 {
public static final Singleton1 INSTANCE=new Singleton1();
private Singleton1() {
}
}
饿汉式Demo2、枚举
/**
*
* @author sprin
* 枚举类型,表示该类型的对象是有限的几个
* 我们可以限定为1个,就是单例了
*/
public enum Singleton2 {
INSTANCE
}
测试
public class Test2 {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println(Singleton1.INSTANCE);
System.out.println(Singleton2.INSTANCE);
}
}
}