学设计模式——单例(Singleton)

单例模式(注意这里是已经创建出的实例)

1、通俗理解: 无论在什么岛屿或国家,国王只有唯一一个

在这里插入图片描述

2、特点:

2.1、只有一个实例。
2.2、能够自我实例化。
2.3、提供全局访问点。

3、使用场景: 线程池、缓存、数据库连接

4、结构:

4.1、单例类:包含一个实例且能自行创建这个实例的类。
4.2、访问类:使用单例的类。

5、实现示例

5.1、饿汉式:一个王国成立的同时国王也就已经生成了。
java
public class King {
    /**
     * 全局属性,体现一下多线程下的不安全性。
     */
    private String param;
    
     /**
      *直接创建实例
      *基础知识:
      * final常量,只被赋值一次。
      * static静态变量,只要程序加载了类的字节码文件,不用创建任何实例象,静态变量就会被分配空 
      * 间,静态变量就可以被使用了
      */
    private static final King king = new King();

    /**
     * 私有无参构造,不允许其他类通过King的构造器创建实例
     */
    private King(){}

    /**
     * 对外开放一个方法让其获取内存中唯一的实例
     */
    public King getKing(){
        return king;
    }

    /**
     * set方法
     * @param param
     */
    public void setParam(String param){
        this.param = param;
    }

    /**
     * get方法
     * @return String
     */
    public String getParam(){
        return this.param;
    }
}
5.2、懒汉式:大家一起打下了天下,这时还没有国王。各自过各自的生活。等有一天其他的部落来侵略,需要有人统领大家反抗时才会创建一个国王。
java
public class Lazy_Singleton {
    /**
    * 在单例对象占用资源大,需要延时加载的情况下优选。
    * 1、使用时生成类
    * 2.volatile关键字防止指令重排
    * 字节码层:
    * JIT、CPU在执行过程中经历下面不在
    * (1)、分配空间
    * (2)、初始化
    * (3)、引用赋值
    * (2)与(3)执行顺序有可能颠倒
    */
    private volatile static Lazy_Singleton instance ;
     /**
      * 功能描述: 创建一个私有的构造,防止被其他类通过构造器实例化
      */
    private Lazy_Singleton(){ }
    /**
     *  静态工厂方法,创建实例
     */
    public static Lazy_Singleton getInstance() {
        /*先判断需要实例化的对象是否空.如果不为空就返回,这样可以提供一些性能,无需再加锁等待。*/
        if(null == instance){
            //加锁,防止多线程同时访问,第一个线程还没有创建完,第二个有来创建的问题。(这里性能
            //会有问题)
            synchronized (Lazy_Singleton.class){
                /*判断是否为空*/
                if(null == instance){
                    instance = new Lazy_Singleton();
                }
                return instance;
            }
        }
        return instance;
    }

    /**
     *  如果该对象被用于序列化,可以保证对象在序列化前后保持一致
     */
    public Object readResolve() {
        return getInstance();
    }
}

5.3.静态内部类:与懒汉式一样使用时创建
public class Instonce_Singleton {
    private static class InstanceHolder{
        private static Instonce_Singleton instance = new Instonce_Singleton();
    }
    public Instonce_Singleton getInstance(){
        return InstanceHolder.instance;
    }
}
5.4、枚举类:

这里首先介绍一下枚举类
枚举类学习链接:

  • 通过对枚举的了解,下面我们进一步了解什么枚举实现单例是一个理想的方式。
  • 首先枚举类是不能通过获取无参构造器反射生成的。应为Constructor类的newInstance方法:有这样的判断
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
	throw new IllegalArgumentException("Cannot reflectively create enum objects");
	ConstructorAccessor ca = constructorAccessor;  
  • 枚举类中的成员被编译后是加了static的。
  • 反序列化的时候则是通过 java.lang.Enum 的 valueOf() 方法来根据名字查找枚举对象。也就是说,序列化的时候只将 成员的 名称输出,反序列化的时候再通过这个名称,查找对于的枚举类型,因此反序列化后的实例也会和之前被序列化的对象实例相同。
  • 补充: 枚举类都继承自Enum,Enum中有一个只有一个参数为(String.class,int.class)构造器。可以看Enum源码发现,这两个参数是name和ordial两个属性。
  • 下面看一下枚举实现单例,
java:
public enum  EnumSingleton {
	INSTANCE;
	public EnumSingleton getInstance(){
		return INSTANCE;
	}
	public void sayHello(){
		System.out.print("sayHello!");
	}
}
//调用
EnumSingleton singleton1=EnumSingleton.INSTANCE;
EnumSingleton singleton1=EnumSingleton.INSTANCE;
singleton1.sayHello();

单例基本也就这些了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值