一、什么是单例模式
1.概念
单实例模式是创建类型的典型软件设计模式。 以单实例模式创建的类“当前进程只有一个实例”(如果需要,也可以“在一个线程上属于单个实例”,例如仅在线程的上下文中使用相同的实例)
单实例模式是指严格控制类的实例,要求一个进程或线程“只存在一个实例”。 如果不存在,则创建并返回实例,如果存在,则返回已经存在的实例。 不同的单实例模式是为了“保证只有一个实例”。
2.常见的例子
暂时想不起来
3.特点
单实例类在一个进程或线程中只能存在一个实例。 单例类的“建构者必须私有化”。 其他类不能创建单个实例类。 只有这样才能创建自己的类。 单实例类必须为其他类提供“获取实例的方法”。 通常是“静态”。4.优点
“减少内存开销”。 单实例模式严格控制只存在一个实例,因此大大减少了实例的“重复创建时的内存开销”。 “易于管理和维护”。 没什么可说的。 所有的内容都写在这个班里。 修改这个类就行了。5.缺点
“可扩展性不强”。 单实例模式只专注于“只有一个实例”,而不是以可扩展性为代价。 “与单一职责的冲突”。 所有方法都封装在单个实例类中,因此变得越来越庞大,责任也越来越不明确。二、单例模式的分类
1.饿汉式
概念
就像饥饿的男人遇到食物一样,马上全部吃掉。 空腹汉表达式的一个示例是,当加载. class文件时,会在静态区域中生成实例,而其他类则调用此类。
代码
打包单个;//*
* @author xxj
* *饿汉一例
*/
公共类hungrysingletion {
privatestatichungrysingletioninstance=newhungrysingletion (;
私有增强()
publicstatichungrysingletiongetinstance (
返回实例;
}
}
特点
饿汉表达式简单粗暴,“立即在静态区域生成实例”、“确保线程安全”、不生成额外的实例,但创建的实例“初始化较慢”。 下一个单一例子的模型是解决这个问题。
2.gxdxhd式
概念
gxdxhd还算懒,不点燃眉毛绝对不工作。 gxdxhd表达式的单个实例只在对其他类调用“提供获取实例的方法”时生成实例,但这存在线程问题。
简单-gxdxhd式
代码
分组化;//*
* @author xxj
* gxdxhd式单壳
*/
公共类lazy单电控{
privatestaticlazysingletoninstance=空;
私有激光单电控
publicstaticlazysingletongetinstance (
if (实例==空值) )。
实例=新激光单电控(;
返回实例;
}
}
特点
的第一个实例指向null,因此没有立即在静态区域中生成实例,而是“延迟加载”,但“线程有问题”。 如果多个线程同时访问获取此实例的方法,则可能会创建多个实例。 因为在“这种极端的状况”下“不能说是单实例模式”,所以是下一个gxdxhd模式 式解决了这个问题。双重检查-gxdxhd式
代码
package singletion; /** * @author xxj * 双重检查gxdxhd式单例 */ public class DoubleCheckLazySingleton { private static volatile DoubleCheckLazySingleton instance =null; public static DoubleCheckLazySingleton getInstance() { if (instance==null){ synchronized (DoubleCheckLazySingleton.class){ if (instance==null){ instance=new DoubleCheckLazySingleton(); } } } return instance; } private DoubleCheckLazySingleton() { } }双重检查
简单点说,「第一次检查」是为了「提高效率」,毕竟并不是所有线程都能转这个空子,这一道检查,就可以拦截大部分的线程了;「第二次检查」才是真正地「解决线程安全问题」,这里加上了synchronized关键字,通过加锁的方式,就可以解决多线程问题了。
特点
继承了简单-gxdxhd式单例的「延迟加载」的特点,也「解决了线程安全问题」,唯一的缺点就是「结构复杂」了。
还有一种gxdxhd式单例模式,就是比双重检查-gxdxhd式单例少第二次检查,那种单例能解决少量线程的线程安全问题,线程数多了,就不能保证了。
下面是两种不常用的单例模式。
3.静态内部类
代码
public class Singleton { private static class SingletonHolder { private static final Singleton instance = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.instance ; } }解释
这种使用静态内部类实现的单例模式,其实是饿汉式的升级版,「首先」是在单例类的内部「创建了一个静态内部类」,内部类里面「有一个单例类的实例」;「然后」,「单例类」给其它类「提供一个获取实例的方法」。 当其它类调用这个方法时,「类加载器」才会去装载内部类,一装载,就会「生成一个单例类的实例」。
特点
不仅继承了饿汉式的「线程安全」的特性,而且实现了「延迟加载」的功能。
4.枚举类
代码
package singletion; /** * @author xxj * 枚举类单例模式 */ public enum EnumSingleton { INSTANCE; public static EnumSingleton getInstance() { return EnumSingleton.INSTANCE; } }特点
首先即使「实现简单方便」,用枚举类实现单例实际上和饿汉式是一样的,它可以保证「线程安全」,但是同样「初始化比较缓慢」。 再说一点,枚举类的确可以实现单例化,我验证过hashCode,都是一样的,但是它的写法就有点让人摸不着头脑。
三、总结
一般情况下,使用饿汉式和枚举类实现就可以了,如果要考虑延迟加载的话,就使用简单-gxdxhd式,再要考虑线程安全问题,就加个双重检查,或者直接使用静态内部类实现。
—————————————————————————————— 如果本文章内容有问题,请直接评论或者私信我。 「未经允许,不得转载!」