栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

设计模式之单例模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

设计模式之单例模式

一、前言

单例模式有很多实现方法,饿汉式、懒汉式、静态内部类、枚举类等等。

二、单例模式分类 一、饿汉式

类加载时初始化,线程安全 。

优点:没有加锁,执行效率会提高。

缺点:类加载时就初始化,分配内存。

基于 classloader 机制避免了多线程的同步问题,

1、静态变量模式

//饿汉式(静态变量)
//加fianl主要是防止子类继承了之后对其修改
//

public final class Singleton implements Serializable{
	
	//1. 构造器私有化, 外部能new
	private Singleton() {
		
	}
	
	//2.本类内部创建对象实例
	private final static Singleton instance = new Singleton();
	
	//3. 提供一个公有的静态方法,返回实例对象
	public static Singleton getInstance() {
		return instance;
	}
	

    //4、防止反序列化时创建多个对象。当反序列化是,发现这个方法会使用这个方法所返回的对象,而不是会使用字节码生成的对象。
   public Object readResolve(){
    
    return instance;
    }

    //5、为什么提供静态方法而不是直接将private final static Singleton instance = new Singleton(); 设置为public。
    //首先是提供public方法而不是设置为public会有更好的封装性,其次是方法还可以支持泛型,直接用成员变量没法支持泛型,最后是在创建单例对象时有更多的控制。
      
}

2、静态代码块模式

class Singleton {
	
	//1. 构造器私有化, 外部能new
	private Singleton() {
		
	}
	

	//2.本类内部创建对象实例
	private  static Singleton instance;
	
	static { // 在静态代码块中,创建单例对象
		instance = new Singleton();
	}
	
	//3. 提供一个公有的静态方法,返回实例对象
	public static Singleton getInstance() {
		return instance;
	}
	
}
二、懒汉式

1、静态变量模式,有线程安全问题

class Singleton {
	private static Singleton instance;
	
	private Singleton() {}
	
	//提供一个静态的公有方法,当使用到该方法时,才去创建 instance
	//即懒汉式
	public static Singleton getInstance() {
		if(instance == null) {
			instance = new Singleton();
		}
		return instance;
	}
}

2、线程安全模式

// 懒汉式(线程安全,同步方法)
class Singleton {
	private static Singleton instance;
	
	private Singleton() {}
	
	//提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题,但是存在性能问题,不推荐使用
	//即懒汉式
	public static synchronized Singleton getInstance() {
		if(instance == null) {
			instance = new Singleton();
		}
		return instance;
	}
}

3、推荐使用的三种模式

第一种:

public final class SingletonDemo {
     //1.私有静态属性
    private static volatile SingletonDemo singletonDemo= null;
    //2.构造方法私有化
    private SingletonDemo() {
    }

    
    public static SingletonDemo getSingletonDemo(){
    //3.
        if (singletonDemo == null){
            synchronized (SingletonDemo.class){
                if (singletonDemo == null){
                 //4.
                    singletonDemo = new SingletonDemo();
                }
            }
        }
        //5.
        return singletonDemo;
    }
}

第二种

// 静态内部类完成, 推荐使用
class Singleton {
	private static volatile Singleton instance;
	
	//构造器私有化
	private Singleton() {}
	
	//写一个静态内部类,该类中有一个静态属性 Singleton,类的加载也是懒惰的,只有用到的时候才会加载,也就是说没如果不调用下面的方法,这个类就不会加载
	private static class SingletonInstance {
		private static final Singleton INSTANCE = new Singleton(); 
	}
	
	//提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
	
	public static synchronized Singleton getInstance() {
		
		return SingletonInstance.INSTANCE;
	}
}

第三种

public class SingletonTest08 {
	public static void main(String[] args) {
		Singleton instance = Singleton.INSTANCE;
		Singleton instance2 = Singleton.INSTANCE;
		System.out.println(instance == instance2);
		
		System.out.println(instance.hashCode());
		System.out.println(instance2.hashCode());
		
		instance.sayOK();
	}
}



//1.枚举单例是如何限制示例个数的?属性定义几个就有几个对象
//2.枚举单例在创建时是否有并发问题?没有,因为属性也是静态成员变量,在类加载器上完成的,是线程安全的
//3.枚举单例能否被反射破坏单例?不能
//4.枚举单例能否被反序列化破坏单例?不能,枚举父类实现了序列化接口,已经解决了反序列化破坏单例的问题
//5.枚举单例属于懒汉式还是饿汉式?饿汉式,属性也是属于静态成员变量,加载即创建对象
//6.枚举单例如果希望加入一些单例创建时的初始化逻辑该如何做?枚举也可以有构造方法,把逻辑加到构造方法中就可以了

//使用枚举,可以实现单例, 推荐
enum Singleton {
	INSTANCE; //属性
	public void sayOK() {
		System.out.println("ok~");
	}
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/731683.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号