单态模式可能是23种创建模式种最简单和容易理解的,创建型模式是主要是为了解决对象的创建的方式,单态则是为了保证创建的对象的唯一性。
模式场景与说明有早期编码经验的开发者一般在N层应用开发中的业务逻辑层和持久层之间会有数据库连接的获取,不管是从缓冲池中获取还是直接连接JDBC,为了避免创建多个示例产生资源的浪费,一般会使用单态模式对创建对象进行控制。实际上除此之外,在类似的池化控制中都可以类似的引入,比如线程池等。此类对象创建一般存在:重(类似数据库连接的获取)、频(使用程度较为频繁)的特点。
实现方式1单态模式实现非常简单,一般只要把握两个要点,就能快速创建一个单态模式的类:
- 控制构造函数:私有化构造函数保证无法随意创建对象
- 统一创建对象:在类中提供对象的构建方法并提供公有方法返回创建的实例(一般为静态函数)
最简单的示例代码如下所示
public class Singleton { // use private key word to avoid being used directly private Singleton() {} private static Singleton instance = new Singleton(); // use public method to get singleton instance public static Singleton getInstance(){ return instance; } }
调用方式:Singleton.getInstance();
这里稍微修改一下,显示一下输出内容,特意在构建函数里添加sleep,可以在多个终端同时启动,可以验证并行时仍然使用同一个实例(hashcode相同)。
package com.liumiao; import java.time.LocalDateTime; public class Singleton { // use private key word to avoid being used directly private Singleton() { System.out.printf("%s: Single instance creating begins... \n" ,LocalDateTime.now()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.printf("%s: Single instance creating ends... \n" ,LocalDateTime.now()); } private static Singleton instance = new Singleton(); // use public method to get singleton instance public static Singleton getInstance(){ System.out.println("get Singleton instance: " + LocalDateTime.now()); System.out.println(instance.hashCode()); return instance; } }
测试代码如下
package com.liumiao; public class TestSingleton extends Thread { public void run() { Singleton.getInstance(); } public static void main( String[] args ) { TestSingleton thread1 = new TestSingleton (); TestSingleton thread2 = new TestSingleton (); thread1.start(); thread2.start(); } }
执行结果如下
2020-06-26T05:37:58.555119: Single instance creating begins... 2020-06-26T05:37:59.583467: Single instance creating ends... get Singleton instance: 2020-06-26T05:37:59.583739 140350290 get Singleton instance: 2020-06-26T05:37:59.583756 140350290实现方式2
由于实现方式1中对于实例的构建在类装载的时候就已经完成,虽然解决了线程的同步,但是即使没有使用到这个实例也会加载,这里修改一下将new的动作移到getInstance中,通过是否为空来判断一下是否需要new进行构建对象,示例代码如下所示:
package com.liumiao; import java.time.LocalDateTime; public class Singleton { // use private key word to avoid being used directly private Singleton() { System.out.printf("%s: Single instance creating begins... \n" ,LocalDateTime.now()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.printf("%s: Single instance creating ends... \n" ,LocalDateTime.now()); } private static Singleton instance = null; // use public method to get singleton instance public static Singleton getInstance(){ System.out.println("get Singleton instance: " + LocalDateTime.now()); if (null == instance) { instance = new Singleton(); } System.out.println(instance.hashCode()); return instance; } }
使用同样的测试代码,执行结果如下,所示
get Singleton instance: 2020-06-26T05:39:00.137037 get Singleton instance: 2020-06-26T05:39:00.137051 2020-06-26T05:39:00.137567: Single instance creating begins... 2020-06-26T05:39:00.137614: Single instance creating begins... 2020-06-26T05:39:01.162630: Single instance creating ends... 140350290 2020-06-26T05:39:01.162630: Single instance creating ends... 1253458049
可以看到,单态出现了问题,产生了不同的实例(hashcode不同),因为没有考虑到线程安全的问题
实现方式3这里简单地使用synchronized来稍作修改, 代码如下
package com.liumiao; import java.time.LocalDateTime; public class Singleton { // use private key word to avoid being used directly private Singleton() { System.out.printf("%s: Single instance creating begins... \n" ,LocalDateTime.now()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.printf("%s: Single instance creating ends... \n" ,LocalDateTime.now()); } private static Singleton instance = null; // use public method to get singleton instance public static synchronized Singleton getInstance(){ System.out.println("get Singleton instance: " + LocalDateTime.now()); if (null == instance) { instance = new Singleton(); } System.out.println(instance.hashCode()); return instance; } }
使用同样的测试代码执行结果如下
get Singleton instance: 2020-06-26T05:42:13.732276 2020-06-26T05:42:13.732766: Single instance creating begins... 2020-06-26T05:42:14.758235: Single instance creating ends... 346203776 get Singleton instance: 2020-06-26T05:42:14.758679 346203776
所以可以看到已经返回了相同的实例了
其他设计模式- https://liumiaocn.blog.csdn.net/article/details/106954154