一、概念
java中单例模式是一种常见的设计模式,单例模式的写法有10多种。
单例模式有以下特点:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
单例模式确保对象只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。一切共享资源都可以考虑设计为单例模式。总之,选择单例模式就是为了避免不一致状态,避免不一致。
二、单例示例
私有化构造:将构造函数声明成私有的,这样可以确保在类的外部无法实例化该类(即在类的外部获取不到类的实例)。
对外提供实例:提供一个全局访问点(其实就是一个全局静态字段),外部可以通过该字段访问该类的唯一实例。因为静态字段是属于类的,所以这样可以保证只有一个实例。
1.普通懒汉单例
//懒汉式:并发情况下,存在非线程安全
public class Singleton02 {
private static Singleton02 singleton=null;
//私有化构造器
private Singleton02() {
}
public static Singleton02 getInstance(){
if (singleton==null){
singleton=new Singleton02();
}
return singleton;
}
}
2.普通饿汉单例
//饿汉式
public class Singleton01 {
static private Singleton01 singleton= new Singleton01();
private Singleton01() {
}
public static Singleton01 getIInstance(){
return singleton;
}
}
3.简单版枚举单例
方式一
//枚举型单例
public enum Singleton03 {
ISTANCE;
//最简洁单例
public void anyMethod(){}
}
方式二
//枚举型单例
public enum Singleton03 {
ISTANCE;
//最简洁单例
private SingletonEntity se;
public SingletonEntity getInstance() {
se = new SingletonEntity();
return se;
}
}
4.线程安全懒汉单例
方式一:同步方法
//线程安全懒汉式(同步方法)
public class Singleton04 {
private static Singleton04 singleton =null;
private Singleton04(){}
public static synchronized Singleton04 getInstance(){
if(singleton==null){
singleton=new Singleton04();
}
return singleton;
}
}
方式二:同步代码块
//线程安全懒汉式(最精简单锁模式)
public class Singleton05 {
private static Singleton05 singleton =null;
private Singleton05(){}
public static Singleton05 getInstance(){
if(singleton==null){
synchronized (Singleton05.class) {
singleton = new Singleton05();
}
}
return singleton;
}
}
方式三:双重锁 -同步代码块
//线程安全懒汉式(双重锁 -同步代码块--此最精简)
public class Singleton06 {
//声明属性volatile检验锁 保其可见性
private static volatile Singleton06 singleton=null;
//私有构造
private Singleton06(){
}
//公有方法
public static Singleton06 getInstance(){
if(singleton==null){
synchronized (Singleton06.class){
singleton=new Singleton06();
}
}
return singleton;
}
}
方式四:静态代码块
//静态代码块版单(线程安全)
public class Singleton07 {
private static Singleton07 singleton=null;
private Singleton11(){}
static{
singleton=new Singleton07();
}
public static Singleton07 getInstance(){
return singleton;
}
}
方式六:静态内部类
//静态内部类单列
public class Singleton08 {
//静态内部类创建实列
private static class MySingleton{
private static Singleton08 instance=new Singleton08();
}
private Singleton08(){}
public static Singleton08 getInstance(){
return MySingleton.instance;
}
}
5.序列化单例
方式一:非线程安全
import java.io.Serializable;
//序列化与反序列化的单列模式(并发情况下,线程不安全版)
public class Singleton09 implements Serializable{
private static final long serialVersionUID = -3690733016505250892L;
private static class MySingleton{
public static Singleton09 instance =new Singleton09();
}
private Singleton09(){}
public static Singleton09 getInstance(){
return MySingleton.instance;
}
}
方式二:线程安全
import java.io.Serializable;
//序列化与反序列化的单列模式(线程安全版)
public class Singleton10 implements Serializable{
private static final long serialVersionUID = 6260883501028235059L;
private static class MySingleton{
private static Singleton10 instance=new Singleton10();
}
private Singleton10(){}
public static Singleton10 getInstance(){
return MySingleton.instance;
}
//为保证线程安全,解决办法就是在反序列化的过程中使用readResolve()方法
protected Object readResolve() throws Exception{
return MySingleton.instance;
}
}
6.复杂枚举单例
方式一:枚举实现细节暴露
//枚举实列2(与静态代码块类似的,但是枚举实现细节暴露)
public enum Singleton11 {
SingletonFactory;
private MySingleton instance;
//枚举的构造方法在类加载时被实列
private Singleton11(){
instance=new MySingleton();
}
public MySingleton getInstance(){
return instance;
}
}
//需要获实现单例的类,比如数据库连接Connection
class MySingleton{
public MySingleton() {
}
}
方式二:枚举实现细节隐藏
//完善版枚举单列(创建枚举内部类,隐藏了实现细节,完善后的单例实现更为合理)
public class ClassFactory {
private enum SingleFactory{
SingletonFactory;
private MySingleton12 instance;
SingleFactory() {
instance=new MySingleton12();
}
public MySingleton12 getInstance(){
return instance;
}
}
public static MySingleton12 getInstance(){
return SingleFactory.SingletonFactory.getInstance();
}
}
//需要获实现单例的类,比如数据库连接Connection
class MySingleton12 {
public MySingleton12() {
}
}
三、总结
**结论:**由结果可以得知单例模式为一个面向对象的应用程序提供了对象惟一的访问点,不管它实现何种功能,整个应用程序都会同享一个实例对象。
实例对象的频繁创建和销毁 比较耗费资源,并发量不大的情况下,公共资源设计为单例可以节省资源开销。单例模式可以在系统设置全局的访问点,优化和共享资源访问,避免了资源的多重占用,减少系统性能的开销。
: