单例模式(Singleton Pattern)是Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。 这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
1.没有使用单例:重复调用会创建多个对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| package java_basic;
class Singleton{ public Singleton(){ } public void print(){ System.out.println("Hello Word"); } }
public class singleton {
public static void main(String[] args) { Singleton s1 = new Singleton(); Singleton s2 = new Singleton(); Singleton s3 = new Singleton(); System.out.println(s1.hashCode()); System.out.println(s2.hashCode()); System.out.println(s3.hashCode()); s1.print(); s2.print(); s3.print(); }
}
|
2.饿汉式单例:(一定是安全的,只有一份对象)
1.构造器私有化
2.声明私有的静态属性,同时创建该对象
3.对外提供访问属性的静态方法,确保该对象存在。
写法1:初始化就加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package java_basic;
class Singleton{ private static Singleton instance = new Singleton();//声明私有的静态属性,同时创建该对象 private Singleton(){ //构造函数私有化 } public static Singleton getInstance(){ //对外提供访问属性的静态方法,确保该对象存在 return instance; } public void print(){ System.out.println("Hello Word"); } }
public class singleton {
public static void main(String[] args) { Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); Singleton s3 = Singleton.getInstance(); System.out.println(s1.hashCode()); System.out.println(s2.hashCode()); System.out.println(s3.hashCode()); s1.print(); s2.print(); s3.print(); }
}
|
可以看到输出的hashCode只有一个,证明new出的对象是同一个
写法2:类在使用的时候加载,懒加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package java_basic;
class Singleton{ // 再定义一个Single类,Single类在使用的时候加载,懒加载 private static class Single{ private static Singleton instance = new Singleton(); //声明私有的静态属性,同时创建该对象 }
private Singleton(){ //构造函数私有化 } public static Singleton getInstance(){ //对外提供访问属性的静态方法,确保该对象存在 return Single.instance; } public void print(){ System.out.println("Hello Word"); } }
public class singleton {
public static void main(String[] args) { Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); Singleton s3 = Singleton.getInstance(); System.out.println(s1.hashCode()); System.out.println(s2.hashCode()); System.out.println(s3.hashCode()); s1.print(); s2.print(); s3.print(); }
}
|
3.懒汉式单例:(不一定安全,确保只有一份对象需要synchronized)
1.构造器私有化
2.声明私有的静态属性
3.对外提供访问属性的静态方法,确保该对象存在。
写法1,多线程下不安全
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package java_basic;
class Singleton{ //懒汉模式,多线程下不安全 private static Singleton instance; //声明私有的静态属性,但是不创建该对象 private Singleton(){ //构造函数私有化 } public static Singleton getInstance(){ //对外提供访问属性的静态方法,确保该对象存在 if(instance == null){ instance = new Singleton(); } return instance; } public void print(){ System.out.println("Hello Word"); } }
public class singleton {
public static void main(String[] args) { Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); Singleton s3 = Singleton.getInstance(); System.out.println(s1.hashCode()); System.out.println(s2.hashCode()); System.out.println(s3.hashCode()); s1.print(); s2.print(); s3.print(); }
}
|
写法2:加锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package java_basic;
class Singleton{ //懒汉模式,加锁 private static Singleton instance; //声明私有的静态属性,但是不创建该对象 private Singleton(){ //构造函数私有化 } public static Singleton getInstance(){ //对外提供访问属性的静态方法,确保该对象存在 if(instance == null){ synchronized(Singleton.class){//加锁 if(null == instance){ instance = new Singleton(); } } } return instance; } public void print(){ System.out.println("Hello Word"); } }
public class singleton {
public static void main(String[] args) { Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); Singleton s3 = Singleton.getInstance(); System.out.println(s1.hashCode()); System.out.println(s2.hashCode()); System.out.println(s3.hashCode()); s1.print(); s2.print(); s3.print(); }
}
|
懒汉式参考:Java学习之线程锁–单例模式写法–synchronized
4.枚举单例:(线程安全)
1 2 3 4 5 6 7 8 9 10 11 12
| public enum Singleton{
//定义1个枚举的元素,即为单例类的1个实例 INSTANCE;
// 隐藏了1个空的、私有的 构造方法 // private Singleton () {}
} // 获取单例的方式: Singleton singleton = Singleton.INSTANCE;
|
《大话设计模式》P232
P
《剑指Offer》P51