单例模式
【概述】
- 采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例
- 并且该类只提供一个取得其对象实例的方法(静态获取方法)
【单例设计模式-八种方式】
- 饿汉式(静态常量)
- 饿汉式(静态代码块)
- 懒汉式(线程不安全)
- 懒汉式(线程安全,同步方法)
- 懒汉式(线程安全,同步代码块)
- 双重检查
- 静态内部类
- 枚举
饿汉式(静态常量&静态代码块)
【操作步骤】
- 构造器私有化(防止 new)
- 类的内部创建对象
- 向外暴露一个静态的公共方法(
getInstance()
)
【实验代码】
//使用静态变量形式
public class Singleton01 {
public static void main(String[] args) {
SingleTon instance1 = SingleTon.getInstance();
System.out.println("instance 值 = " + instance.getValue());
instance1.setValue(8);
SingleTon instance2 = SingleTon.getInstance();
System.out.println("instance2 值 = " + instance2.getValue());
System.out.println("instance1 hashCode = " + instance1.hashCode());
System.out.println("instance2 hashCode = " + instance2.hashCode());
}
}
class SingleTon{
int value = 1;
//1. 本类内部创建对象实例
private static final SingleTon instance = new SingleTon();
//2. 构造方法私有化,不能New
private SingleTon(){}
//3. 对外提供一个公有的静态方法,返回实例对象
public static SingleTon getInstance(){
return instance;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
//使用静态代码块形式
public class Singleton01 {
public static void main(String[] args) {
SingleTon instance1 = SingleTon.getInstance();
System.out.println("instance1 值 = " + instance1.getValue());
instance1.setValue(8);
SingleTon instance2 = SingleTon.getInstance();
System.out.println("instance2 值 = " + instance2.getValue());
System.out.println("instance1 hashCode = " + instance1.hashCode());
System.out.println("instance2 hashCode = " + instance2.hashCode());
}
}
class SingleTon{
int value = 1;
//1. 本类内部创建对象实例
private static final SingleTon instance;
//在静态代码块中创建单例对象
static {
instance = new SingleTon();
}
//2. 构造方法私有化,不能New
private SingleTon(){}
//3. 对外提供一个公有的静态方法,返回实例对象
public static SingleTon getInstance(){
return instance;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
【运行结果】
可以看到:
instance1 获取的value 是
类SingleTon
初始定义值通过instance1
setValue()
后instance2 获取的value任然是instance设置的值
instance1 和 instance2的 hashCode 完全一样
【优点】
- 两者都是写法简单
- 在类装载的时候就完成了实例化,避免了线程同步
【缺点】
因为类装载(类的装载可能有多种方式)的时候就完成实例化,**没有实现Lazy Loading(懒加载)**的效果。
即 如果没有使用到该类时就装载,这种单例模式 可能造成内存浪费