一、定义
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
二、要点
某个类只能有一个实例;
单例类必须自己创建自己的实例;
单例类必须向整个系统提供这个实例;
三、单例模式的类图
四、设计模式代码
1.饿汉模式(类加载的时候实例化对象)
package singletonPattern;
/**
* 饿汉模式
*/
public class SingletonHungry {
private static SingletonHungry singletonHungry = new SingletonHungry();
/**
* 通过private,限制产生多个实例
*/
private SingletonHungry(){
}
public static SingletonHungry getInstance(){
return singletonHungry;
}
public void doSomthing(){
System.out.println("SingletonHungry do something!!!");
}
}
2.懒汉模式(类加载的时候只是进行声明,调用这个类的时候才实例化)
(1)线程不安全模式
package singletonPattern;
/**
* 懒汉模式,线程不安全
*/
public class SingletonLazyUnsafe {
private static SingletonLazyUnsafe singletonLazyUnsafe = null;
/**
* 限制产生多个实例
*/
private SingletonLazyUnsafe(){
}
public static SingletonLazyUnsafe getInstance(){
singletonLazyUnsafe = new SingletonLazyUnsafe();
return singletonLazyUnsafe;
}
public void doSomthing(){
System.out.println("SingletonLazyUnsafe do something!!!");
}
}
(2)线程安全模式
package singletonPattern;
/**
* 懒汉模式,线程安全
*/
public class SingletonLazySafe {
private static SingletonLazySafe singletonLazySafe = null;
/**
* 限制产生多个实例
*/
private SingletonLazySafe(){
}
public static SingletonLazySafe getInstance(){
/**
* 当第一次调用getInstance操作时,即singletonLazySafe为空时,同步操作,保证多线程实例唯一
* 当以后调用getInstance操作时,即singletonLazySafe不为空时,不进入同步代码块
*/
if(singletonLazySafe == null) {
synchronized (SingletonLazySafe.class){
if(singletonLazySafe == null) {
singletonLazySafe = new SingletonLazySafe();
}
}
}
return singletonLazySafe;
}
public void doSomthing(){
System.out.println("SingletonLazySafe do something!!!");
}
}
4.有上限的多例模式(一个类只能产生多个实例,实例的数量受限制)
package singletonPattern;
import java.util.ArrayList;
import java.util.Random;
/**
* 有上限的多例模式
*/
public class SingletonExtend {
//定义最多产生的实例数量
private static int max = 3;
//定义一个列表,用来保存所有的实例
private static ArrayList<SingletonExtend> array = new ArrayList<>();
//保存每个实例的名字
private static ArrayList<String> namList = new ArrayList<>();
//第几个实例
private static int count = 0;
static {
for(int i = 0; i < max; i++)
array.add(new SingletonExtend("第" + i+1 + "个实例!"));
}
/**
* 限制其他类生成实例
*/
private SingletonExtend(){
}
private SingletonExtend(String name){
namList.add(name);
}
/**
* 随机获得一个实例对象
* @return
*/
public static SingletonExtend getInstance(){
Random random = new Random();
count = random.nextInt(max);
return array.get(count);
}
public void doSomthing(){
System.out.println("SingletonExtend " + count + " do something!!!");
}
}
对比:
懒汉模式:类加载快,获取对象慢,线程不安全(需要进行synchronized)
饿汉模式:类加载慢,获取对象快,线程安全
五、优缺点
优点:
单例模式在内存中只有一个实例,减少了内存开支,特别是一个对象需要频繁的创建和销毁时;
减少了系统的性能开销,当一个对象的产生需要较多的资源时,如读取配置、产生其他依赖对象时;
避免对资源的多重占用,例如写文件时,只有一个实例存在内存中。
缺点:
单例模式一般没有接口,扩展困难;
单例模式与单一职责原则冲突,一个类应该只实现一个逻辑,而不关心它是否是单例的。