单例模式的定义
定义:Ensure a class has only one instance, and provide a global point of access to it.(确保某一个类
只有一个实例,而且自行实例化并向整个系统提供这个实例。)
单例模式的通用代码:
public class Singleton {//饥汉式
private static final Singleton singleton = new Singleton();
//限制产生多个对象
private Singleton() {
}
//通过该方法获得实例对象
public static Singleton getSingleton() {
return singleton;
}
//类中的其他方法,尽量static
public static void doSomething() {
}
}
单例模式的应用
单例模式的优点
- 减少内存开支
- 减少系统的性能开销
- 避免对资源的多重占用
- 设置全局访问点,优化和共享资源访问
单例模式的缺点
- 单例模式没有接口,扩展困难
- 单例模式对测试不利
- 单例模式与单一职责冲突
单例模式的使用场景
- 要求生成唯一序列号的环境
- 需要一个共享的访问点或共享数据(Web页面的计数器)
- 创建一个对象消耗的资源过多(访问IO和数据库)
- 需要定义大量静态常量和静态方法(如工具类)的环境(也可以直接声明为static方法)
单例模式的注意事项
高并发情况下,单例模式的线程同步问题
上一段代码不会出现产生多个实例的情况,但是,下面这个就可能了
public class Singleton {//懒汉式(synchronized关键字解决线程同步问题)
private static Singleton singleton = null;
//限制产生多个对象
private Singleton() {
}
//通过该方法获得实例对象
public synchronized static Singleton getSingleton() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
//类中的其他方法,尽量static
public static void doSomething() {
}
}
单例模式的扩展
产生固定数量对象的模式------有上限的多例模式,他是单例模式的扩展,采用有上限的多例模式,我们可以在设计是决定在内存中有多少个实例,方便系统进行扩展,修正单例可能存在的性能问题,提供系统的响应速度。(读取文件,我们可以在系统启动时完成初始化工作,在内存中启动固定数量的reader实例,在需要读取文件时就可以快速响应)
public class Emperors {
private static int maxNumOfEmperor = 2;
private static ArrayList<String> nameList = new ArrayList<>();
private static ArrayList<Emperors> emperorList = new ArrayList<>();
private static int countNumOfEmperor = 0;
static {
for (int i = 0; i <maxNumOfEmperor ; i++) {
emperorList.add(new Emperors("黄" + i + "帝"));
}
}
private Emperors() {
}
private Emperors(String name) {
nameList.add(name);
}
public static Emperors getInstance() {
Random random = new Random();
countNumOfEmperor = random.nextInt(maxNumOfEmperor);
return emperorList.get(countNumOfEmperor);
}
public void say() {
System.out.println(nameList.get(countNumOfEmperor));
}
}