保证一个类只有一个实例, 并提供一个访问该实例的全局节点java
1) 对惟一实例的受控访问数据库
2) 得到指向该实例的全局访问节点缓存
3) 仅在首次请求单例对象时进行初始化安全
4) 违反了单一职责原则。 该模式同时解决了两个问题(在一个方法中进行了建立类和提供类对象的操做)多线程
5) 单例模式可能掩盖不良设计, 好比程序各组件之间相互了解过多等app
6) 该模式在多线程环境下须要进行特殊处理, 避免多个线程屡次建立单例对象框架
7) 单例的客户端代码单元测试可能会比较困难, 由于许多测试框架以基于继承的方式建立模拟对象。 因为单例类的构造函数是私有的, 并且绝大部分语言没法重写静态方法, 因此你须要想出仔细考虑模拟单例的方法。 要么干脆不编写测试代码, 或者不使用单例模式less
Singleton_singlethread.java: 单例(单线程)ide
package singleton; /** * @author GaoMing * @date 2021/7/18 - 19:13 */ public class Singleton_singlethread { private static Singleton_singlethread instance; public String value; private Singleton_singlethread(String value) { // The following code emulates slow initialization. try { Thread.sleep(1000); } catch (InterruptedException ex) { ex.printStackTrace(); } this.value = value; } public static Singleton_singlethread getInstance(String value) { if (instance == null) { instance = new Singleton_singlethread(value); } return instance; } }
DemoSingleThread.java: 客户端代码函数
package singleton; /** * @author GaoMing * @date 2021/7/18 - 19:16 */ public class DemoSingleThread { public static void main(String[] args) { System.out.println("If you see the same value, then singleton was reused (yay!)" + "\n" + "If you see different values, then 2 singletons were created (booo!!)" + "\n\n" + "RESULT:" + "\n"); Singleton_singlethread singleton = Singleton_singlethread.getInstance("FOO"); Singleton_singlethread anotherSingleton = Singleton_singlethread.getInstance("BAR"); System.out.println(singleton.value); System.out.println(anotherSingleton.value); } }
执行结果
If you see the same value, then singleton was reused (yay!) If you see different values, then 2 singletons were created (booo!!) RESULT: FOO FOO
Singleton_multithread.java: 单例(多线程安全单例)
package singleton; /** * @author GaoMing * @date 2021/7/18 - 19:12 */ public final class Singleton_multithread { private static volatile Singleton_multithread instance; public String value; private Singleton_multithread(String value) { this.value = value; } public static Singleton_multithread getInstance(String value) { // The approach taken here is called double-checked locking (DCL). It // exists to prevent race condition between multiple threads that may // attempt to get singleton instance at the same time, creating separate // instances as a result. // // It may seem that having the `result` variable here is completely // pointless. There is, however, a very important caveat when // implementing double-checked locking in Java, which is solved by // introducing this local variable. // // You can read more info DCL issues in Java here: // https://refactoring.guru/java-dcl-issue Singleton_multithread result = instance; if (result != null) { return result; } synchronized(Singleton_multithread.class) { if (instance == null) { instance = new Singleton_multithread(value); } return instance; } } }
DemoMultiThread.java: 客户端代码
package singleton; /** * @author GaoMing * @date 2021/7/18 - 19:30 */ public class DemoMultiThread { public static void main(String[] args) { System.out.println("If you see the same value, then singleton was reused (yay!)" + "\n" + "If you see different values, then 2 singletons were created (booo!!)" + "\n\n" + "RESULT:" + "\n"); Thread threadFoo = new Thread(new ThreadFoo()); Thread threadBar = new Thread(new ThreadBar()); threadFoo.start(); threadBar.start(); } static class ThreadFoo implements Runnable { @Override public void run() { Singleton_multithread singleton = Singleton_multithread.getInstance("FOO"); System.out.println(singleton.value); } } static class ThreadBar implements Runnable { @Override public void run() { Singleton_multithread singleton = Singleton_multithread.getInstance("BAR"); System.out.println(singleton.value); } } }
执行结果
If you see the same value, then singleton was reused (yay!) If you see different values, then 2 singletons were created (booo!!) RESULT: BAR BAR
识别方法: 单例能够经过返回相同缓存对象的静态构建方法来识别。