校招准备系列:每天一道算法题(9)-单例
来源:互联网 发布:pdf阅读器下载 知乎 编辑:程序博客网 时间:2024/05/08 09:09
校招准备系列:每天一道算法题(9)-单例
单例 是最为最常见的设计模式之一。对于任何时刻,如果某个类只存在且最多存在一个具体的实例,那么我们称这种设计模式为单例。例如,对于 class Mouse (不是动物的mouse哦),我们应将其设计为 singleton 模式。
你的任务是设计一个 getInstance 方法,对于给定的类,每次调用 getInstance 时,都可得到同一个实例。
思考:首先,我们来了解一下单例模式,单例模式是一种对象创建模式,用于产生一个对象的具体实例,他可以确保系统中一个类只产生一个实例,其好处在于:1)对于频繁使用 对象,可以省略创建对象所花费的时间,尤其对于一些重量级对象;2)由于new操作次数减少,因而对系统内存的使用频率也会降低,能减轻GC压力,缩短GC停顿时间!So,对于系统的关键组件和被频繁使用的对象使用单例模式可以有效的改善系统的性能。。。
单例模式的核心在于通过一个接口返回唯一的对象实例!
代码:
/** * 单例模式:饿汉式 */public class SingletonDemo1 { private SingletonDemo1(){ } private static SingletonDemo1 instance = new SingletonDemo1();//static实例变量在类加载到内存时就会初始化 线程安全 public static SingletonDemo1 getInstance(){ return instance; }}
从饿汉式代码我们可以看出,1)单例类必须有一个private的构造函数,只有这样才能确保单例不会在系统中的其他代码内被实例化;2)instance成员变量和getInstance()方法必须是static的。
阅读饿汉式单例类的代码,我们知道,其不足在于无法对instance实例做延迟加载,static实例变量在类加载到内存时就会初始化,单例对象就会被创建,其创建的对象是线程安全的!
改进代码:
/** * 单例模式:饱汉式 */public class SingletonDemo2 { private SingletonDemo2(){ } private static SingletonDemo2 instance = null; public static synchronized SingletonDemo2 getInstance(){ if (instance == null) { instance = new SingletonDemo2(); } return instance; }}
在这里的处理中,我们首先对静态成员变量instance初始值赋值null,确保系统启动时没有额外的负载;其次在getInstance()工厂方法中,判断当前单例是否已经创建,若存在则返回,否则就再简历单例!
PS:方法中使用了Synchronized关键字,避免多线程环境下,导致多个单例创建!
饱汉式单例模式虽然解决了延迟加载的问题,但加入Synchronized关键字却增加了系统的开销,所以还需要进一步改进,想到的方法是使用内部类,这种方式使用内部类维护单例的实例,当SingletonDemo3 被加载的时候其内部类并不会被初始化,故可确保SingletonDemo3 类被加载到jvm时,不会初始化单例类,而当调用getInstance方法时,才会加载SingletonHolder,从而初始化instance,同时,由于其实例的建立是在类加载时完成,故天生对多线程友好,不需使用同步关键字,实现代码如下:
/** * 单例模式:内部类 */public class SingletonDemo3 { private SingletonDemo3(){ } private static class SingletonHolder{ private static SingletonDemo3 instance = new SingletonDemo3();} public static SingletonDemo3 getInstance(){ return SingletonHolder.instance; }}
当然除了上面三种方式实现单例模式,我们还有常用的一种最简单的方法,那就是枚举!!
/** * 枚举类方式 最佳实践 推荐 */public enum SingletonDemo3 { INSTANCE; public static void say(String str){ System.out.println("hello"+str); }}
- 校招准备系列:每天一道算法题(9)-单例
- 校招准备系列:每天一道算法题(1)
- 校招准备系列:每天一道算法题(2)
- 校招准备系列:每天一道算法题(3)
- 校招准备系列:每天一道算法题(4)
- 校招准备系列:每天一道算法题(5)-两数之和
- 校招准备系列:每天一道算法题(6)-连续最大和
- 校招准备系列:每天一道算法题(7)-末尾0的个数
- 校招准备系列:每天一道算法题(8)-进制转换
- 校招准备系列:每天一道算法题(10)-二维数组查找
- 校招准备系列:每天一道算法题(11)-替换空格
- 校招准备系列:每天一道算法题(12)-从尾到头打印链表
- 校招准备系列:每天一道算法题(13)-斐波那契数列
- 校招准备系列:每天一道算法题(14)-合并两个排序的链表
- 校招准备系列:每天一道算法题(15)-求1+2+3+...+n
- 【每天一道算法题】
- 【每天一道算法题】
- 【每天一道算法题】
- 简谈JAVA基础--IO流
- nginx学习随笔--pid
- jsp简介和el标签 jstl标签
- python安装numpy、scripy失败总结
- 树状数组求逆序数
- 校招准备系列:每天一道算法题(9)-单例
- table border合并无间隙 列宽度固定不换行
- 精致傲娇的品牌 只卖呆萌的价格 对对全自动外卖打印机评测
- 设计模式转载
- Struts1的标签及意义
- java基础(个人学习笔记)A
- Android Studio教程从入门到精通
- C# 实现AOP 的几种常见方式
- 技术文章 | 如何构建AI驱动型智能服务?