单例设计模式

mac2026-04-07  6

目录

应用场景:

要点:

常见的形式:

饿汉式:直接创建对象,不存在线程安全问题

1、直接实例化饿汉式(简洁直观)

2、枚举式(最简洁)

3、静态代码块饿汉式(适用复杂实例化)*

懒汉式:延迟创建对象

1、线程不安全(适用于单线程)

2、线程安全(适用于多线程)

3、静态内部类形式(适用于多线程)


应用场景:

单例模式可以解决一个需要全局使用的类进行频繁的创建和销毁,节省开销。

单例应用场景:

1.Windows的任务管理器,只能打开一个任务管理器。

2.Windows系统的回收站。

3.网站的计数器,通过单例模式可以很好实现。

4.应用程序的日志应用,一般都何用单例模式实现,这是由于系统一般共用一个日志。

5.数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。

6.多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。

要点:

1、某个类只能有一个实例

==>私有化构造器

2、它必须自行创建这个实例

==>含有一个该类的静态变量来保存这个唯一的实例

3、它必须向整个系统提供这个实例

==>对外提供获取该类的方式(1)直接暴露(2)用静态变量的get方法获取

 

常见的形式:

 

饿汉式:直接创建对象,不存在线程安全问题

1、直接实例化饿汉式(简洁直观)

package singleton; /** * 饿汉式,先造对象,不管你需不需要,都会创建 (1)私有化构造器 (2)自行创建,并用静态变量保存 (3)向外提供这个实例 (4)强调这是一个单例可以用final修饰(不可更改变为常量) * @author YAN */ public class Singleton01 { //1、私有化静态不可变的对象 public static final Singleton01 instance =new Singleton01(); //2、私有化构造器 private Singleton01(){ } public static void main(String[] args) { Singleton01 s1 = Singleton01.instance; Singleton01 s11 = Singleton01.instance; System.out.println(s1==s11); } }

2、枚举式(最简洁)

package singleton; /**jdk1.5枚举类型,表示该类型的对象是有限的几个 我们可以限定为一个,就成了单例(与singleton01效果一样) * 枚举方式最简洁 * @author YAN */ public enum Singleton02 { instance; public static void main(String[] args) { Singleton02 s2 = Singleton02.instance; Singleton02 s22 = Singleton02.instance; System.out.println(s2==s22); } }

3、静态代码块饿汉式(适用复杂实例化)*

如创建对象的形参是properties文件中的value值时

package singleton; import java.io.IOException; import java.util.Properties; public class Singleton03 { public static final Singleton03 instance; private String info; static{ Properties pro = new Properties(); try { pro.load(Singleton03.class.getClassLoader().getResourceAsStream("single.properties")); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } instance = new Singleton03(pro.getProperty("info")); } private Singleton03(String info){ this.info=info; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } public static Singleton03 getInstance() { return instance; } @Override public String toString() { return "Singleton03 [info=" + info + "]"; } public static void main(String[] args) { Singleton03 s3 = Singleton03.instance; Singleton03 s33 = Singleton03.instance; System.out.println(s3); System.out.println(s33); } }

结果如下

懒汉式:延迟创建对象

1、线程不安全(适用于单线程)

package singleton; /** * 懒汉式,最后创建对象 * (1)私有化构造器 * (2)提供一个静态变量保存这个唯一的实例 * (3)提供一个静态方法获取这个实例对象 * @author YAN */ public class Singleton04 { //不用public修饰防止直接调用instance为空 private static Singleton04 instance; private Singleton04(){ } public static Singleton04 getInstance(){ if(instance==null){ instance = new Singleton04(); } return instance; } public static void main(String[] args) { Singleton04 s4 = Singleton04.getInstance(); Singleton04 s44 = Singleton04.getInstance(); System.out.println(s4==s44); } }

2、线程安全(适用于多线程)

package singleton; /** * 懒汉式,最后创建对象 (1)私有化构造器 (2)提供一个静态变量保存这个唯一的实例 (3)提供一个静态方法获取这个实例对象 * * @author YAN */ public class Singleton05 { // 不用public修饰防止直接调用instance为空 static Singleton05 instance; private Singleton05() { } public static Singleton05 getInstance() { if (instance == null) {// 为了提高效率 synchronized (Singleton05.class) {// 加锁后线程安全 if (instance == null) { instance = new Singleton05(); } } } return instance; } public static void main(String[] args) { Singleton05 s5 = Singleton05.getInstance(); Singleton05 s55 = Singleton05.getInstance(); System.out.println(s5 == s55); } }

3、静态内部类形式(适用于多线程)

package singleton; /** * 静态内部类不会随着外部类的加载和初始化而被初始化的 * 它是单独进行初始化的 * 因为是在内部类加载时才会被创建所以线程是安全的 * @author YAN * */ public class Singleton06 { private Singleton06(){ } //当内部类加载和初始化才会创建对象 public static class inner { private static final Singleton06 instance = new Singleton06(); } //当调用getInstance()方法时内部类会初始化创建对象 public static Singleton06 getInstance(){ return inner.instance; } public static void main(String[] args) { Singleton06 s6 = Singleton06.getInstance(); Singleton06 s66 = Singleton06.getInstance(); System.out.println(s6==s66); } }

总结:      一般采用饿汉式,若对资源十分在意可以采用静态内部类,不建议采用懒汉式及双重检测

最新回复(0)