保证某个类只能存在一个对象实例,并提供一个去的对象实例的静态方法
饿汉写法(我们还是去用new的方式创建对象)
package com.company.method;
public class SingletonModeTest1 {
//这里会报错,提示:'Singleton()' has private access in 'com.company.method.Singleton'
Singleton singleton = new Singleton();
}
class Singleton{
//创建一个私有的构造函数
private Singleton(){};
//本类内部创建一个对象实例
private final static Singleton instance = new Singleton();
//提供一个公共的方法获取对象实例
public Singleton getInstance(){
return instance;
}
}
正确的用法
package com.company.method;
public class SingletonModeTest1 {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
//验证是否真的相等
System.out.println(instance == instance1);
System.out.println(instance.hashCode());
System.out.println(instance1.hashCode());
}
}
class Singleton{
//创建一个私有的构造函数
private Singleton(){};
//本类内部创建一个对象实例
private final static Singleton instance = new Singleton();
//提供一个公共的方法获取对象实例
public static Singleton getInstance(){
return instance;
}
}
还有一种写法
package com.company.method;
public class SingletonModeTest2 {
public static void main(String[] args) {
Singleton2 instance = Singleton2.getInstance();
Singleton2 instance1 = Singleton2.getInstance();
//验证是否真的相等
System.out.println(instance == instance1);
System.out.println(instance.hashCode());
System.out.println(instance1.hashCode());
}
}
class Singleton2{
//创建一个私有的构造函数
private Singleton2(){};
//本类内部创建一个对象实例
private static Singleton2 instance;
static {
instance = new Singleton2();
}
//提供一个公共的方法获取对象实例
public static Singleton2 getInstance(){
return instance;
}
}
这样写的优缺点
优点:写法简单,没有线程安全问题
缺点:可能会造成资源浪费,即使没有用到也会被创建
是否可用:可用,可能造成资源浪费
还有一种是懒汉式的创建方式
package com.company.method;
public class SingletonModeTest3 {
public static void main(String[] args) {
Singleton3 instance = Singleton3.getInstance();
}
}
class Singleton3{
//创建一个私有的构造函数
private Singleton3(){};
//本类内部创建一个对象实例
private static Singleton3 instance;
//提供一个公共的方法获取对象实例
public static Singleton3 getInstance(){
if (instance == null){
instance = new Singleton3();
}
return instance;
}
}
懒汉式特点
虽然起到了懒加载,但是在多线程的情况下可能会造成线程重复创建
是否可用:不推荐使用
还有一种比较推荐的写法
package com.company.method;
public class SingletonModeTest3 {
public static void main(String[] args) {
Singleton3 instance = Singleton3.getInstance();
}
}
class Singleton3{
//创建一个私有的构造函数
private Singleton3(){};
//本类内部创建一个对象实例
private static Singleton3 instance;
//提供一个公共的方法获取对象实例
public static Singleton3 getInstance(){
if (instance == null){
synchronized (Singleton3.class) {
if (instance == null) {
instance = new Singleton3();
}
}
}
return instance;
}
}
上述的写法是比较推荐的一种写法
接下来是静态内部类的实现,利用jvm类加载机制
package com.company.method;
public class SingletonModeTest4 {
public static void main(String[] args) {
Singleton4 instance = Singleton4.getInstance();
Singleton4 instance2 = Singleton4.getInstance();
System.out.println(instance == instance2);
}
}
class Singleton4{
//创建一个私有的构造函数
private Singleton4(){};
private static class Singleton4Instance{
private final static Singleton4 INSTANCE = new Singleton4();
}
//提供一个公共的方法获取对象实例
public static Singleton4 getInstance(){
return Singleton4Instance.INSTANCE;
}
}
这样的一个方法也是推荐使用的
下面我们来讲一下单例模式的应用场景
1、工具类的实例化,一个项目有一个工具类其实就可以了,这样可以避免工具类被频繁的被创建
2、还有频繁访问的对象,比如数据源和session工厂
3、重对象的创建