经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
设计模式 | 单例模式(singleton)
来源:cnblogs  作者:莫愆  时间:2019/6/10 13:43:50  对本文有异议

定义:

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

结构:(书中图,侵删)

结构超简单。就在你想控制实例数的类上操作即可。
1.定义一个static的对象引用
2.私有化构造方法
3.提供一个获取实例的方法(static的)
 

实例:

这又是一个在面试中频繁出现的设计模式,我至今不知道为什么大家那么偏爱这个模式。
而且基本上都是让你现场写一个单例模式的例子,基于这个很现实的原因,这个模式也好好好掌握。
我这里就不举生活中的例子了,直接上代码。
 
单例模式又分为两种形式:
一、饿汉式:在类加载是就初始化实例。
二、懒汉式:在第一次调用的时候,才初始化实例。
 
饿汉式:
  1. package designpattern.singleton;
  2. public class HungrySingleton {
  3. private static HungrySingleton instance = new HungrySingleton();// 静态初始化
  4.  
  5. private HungrySingleton() {// 私有化构造方法
  6. }
  7. public static HungrySingleton GetInstance() {// 获取实例,static的
  8. return instance;
  9. }
  10. }
懒汉式:
  1. package designpattern.singleton;
  2. public class LazySingleton {
  3. private static LazySingleton instance;
  4. private LazySingleton() {// 私有化构造方法
  5. }
  6. public static LazySingleton getInstance() {// 获取实例,static的
  7. if (instance == null) {
  8. instance = new LazySingleton();// 方法中创造实例
  9. }
  10. return instance;
  11. }
  12. }
但是,如果是在多线程的情况下,可能会造成创造出两个实例的情况,可以考虑在getInstance方法上加上synchronized修饰:
  1. package designpattern.singleton;
  2. public class LazySingleton2 {
  3. private static LazySingleton2 instance;
  4. private LazySingleton2() {
  5. }
  6. public static synchronized LazySingleton2 getInstance() {// synchronized 修饰
  7. if (instance == null) {
  8. instance = new LazySingleton2();
  9. }
  10. return instance;
  11. }
  12. }
这个可以进一步优化,只让线程在还没有实例化的情况下加锁:
  1. package designpattern.singleton;
  2. import java.util.concurrent.locks.Lock;
  3. import java.util.concurrent.locks.ReentrantLock;
  4. public class LazySingleton3 {
  5. private static LazySingleton3 instance;
  6. private static Lock lock = new ReentrantLock();
  7. private LazySingleton3() {
  8. }
  9. public static synchronized LazySingleton3 getInstance() {
  10. try {
  11. if (instance == null) {
  12. lock.lock();
  13. if (instance == null) {// 有必要再次判断,不然还是存在线程安全问题
  14. instance = new LazySingleton3();
  15. }
  16. lock.unlock();
  17. }
  18. } finally {// 保证锁被释放
  19. lock.unlock();
  20. }
  21. return instance;
  22. }
  23. }

总结:

饿汉式,在类加载是就初始化实例,要提前占用系统资源,但是不用考虑多线程访问可能造成的创建多个实例的问题。
懒汉式,在第一次调用的时候,才初始化实例,不用提前占用系统资源,但是需要考虑到多线程访问的问题。
这个模式在所有需要控制实例数的情况下都能使用,最常见的两个例子,就是数据库连接池和线程池。
以下原因引用自https://www.cnblogs.com/gmq-sh/p/5948379.html《单例模式的常见应用场景》:
数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。
 

原文链接:http://www.cnblogs.com/imoqian/p/10986927.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号