可以说是单例模式中写法最简单的一个方式,这个就是饿汉式,也就是在类加载的时候,就完成实例化,那他虽然简单,
有没有什么值得研究的地方呢,当然是有的,首先我们先完成一个饿汉式的简单实现
package com.learn.design.pattern.creational.singleton;
import java.io.Serializable;
/**
*
* @author Leon.Sun
*
*/
public class HungrySingleton implements Serializable,Cloneable{
/**
* 我们直接声明
* 让我们引用类名来做hungrySingleton
* 我们首先new一个HungrySingleton
* 也就是说在类加载的时候
* 就初始化了
* 当然这个在类加载的时候就初始化
* 我们可以把它做成final的
* 这样这个对象就不可改了
* 在类加载的时候就初始化加载好了
* 也不需要更改了
* 这个final看具体的情况
* 这个就是一个非常简单的饿汉式
* 优点是写法简单
* 类加载的时候就完成了初始化
* 避免了线程同步的问题
* 缺点也是应为在类加载的时候呢就完成初始化
* 没有延迟加载的效果
* 如果这个类从始至终我的系统没有用过
* 那会造成内存的浪费
* 我们也可以把这个实例化的过程放到静态代码块里面
*
*
*
*/
private final static HungrySingleton hungrySingleton;
/**
* 我们试一下static
* 我们使用过静态块
* 来初始化properties的配置文件
*
*
*/
static{
/**
* 然后new一下
* 这里报红线了
* 因为上面是final的
* 也给他初始化了
* 所以静态块里边
* 并不能初始化
* 如果用静态块的话
* 我们可以把后面的new删除掉
* private final static HungrySingleton hungrySingleton;
* 这样就可以了
* 那声明为final的变量
* 必须在类加载完成时
* 已经赋值
* 第一种方式呢
* 直接new出来
* 或者放到静态块里边
* 这个都能完成在类加载的时候就完成赋值
* 所以在lazy这种模式里边
* 它是不能修饰成final的
* 因为他不是在类加载的时候就初始化好
* 那对于饿汉式呢
* 有用final的
* 也有不用final的
* 都可以
* 因为饿汉和懒汉之间
* 最大的区别就是延迟加载
* 是在类加载的时候初始化
* 还是调用之后初始化
* 那这个修饰符我们也要注意
* 这两个效果都是一样的
* 只不过hungrySingleton在内存加载的时候
* 把这个创建对象的过程
* 放到了静态代码块里边
* 那类加载的时候
* 也会执行静态代码块中的代码
* 进行初始化这个类的实例
* 看上去饿汉式是最简单的
* 如果我们的资源浪费少的话
* 用这种方式也是可以的
* 因为这种方式比较简单
* 就不领着debug了
* 多线程的时候也是没有问题的
* 因为类加载的时候就初始化好了
* 所以这里面也不用做空判断
* 直接返回就可以了
* 那这个就称之为饿汉式
* 前面我们还学过懒汉式
* 那有什么技巧吗
* 很简单
* 饿汉式因为它很饿
* 一上来就想吃东西
* 所以就把这个对象一上来就new好了
* 而懒汉式呢
* 非常懒
* 你不用他的时候他都不用创建对象
* 可以利用这个记忆技巧记忆一下
* 免得弄混
* 我们会挖掘其他的安全隐患
*
*
*
*/
hungrySingleton = new HungrySingleton();
}
/**
* 然后private的构造器
*
*/
private HungrySingleton(){
if(hungrySingleton != null){
throw new RuntimeException("单例构造器禁止反射调用");
}
}
public static HungrySingleton getInstance(){
/**
* 直接return
*
*/
return hungrySingleton;
}
private Object readResolve(){
return hungrySingleton;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return getInstance();
}
}