设计模式-创建型之单例模式
来源:互联网 发布:新浪微博怎么修改域名 编辑:程序博客网 时间:2024/05/29 15:39
模式动机
在软件开发中,对于某些特定的类来说,只存在一个实例尤为重要,比如一个系统中的ID生成器。但如何才能保证这个类只有一个实例同时又容易被访问呢?一个比较好的解决办法是让这个类自身负责创建和保存它的唯一实例,并且它需要提供一个方法,用于获取该唯一实例。
模式定义
一个类只有一个实例,这个类在自身内部进行实例化,并把此唯一实例提供给整个系统,即提供一个该实例的访问方法。这个类就叫单例类,这种模式就就单例模式。单例模式也叫单件模式或者单态模式。单例模式主要有三个要点:
- 某个类只能有一个实例;
- 自行创建该实例;
- 提供访问该实例的方法。
模式结构
单例类拥有一个私有的构造方法,这样可以防止其他类通过new关键字来进行实例化它,同时,还包含一个静态私有成员变量(instance)和公有的静态方法(getInstance)来负责提供访问该唯一实例的入口。
单例模式的几种实现方式
饿汉式
public class Singleton { private static Singleton instance = new Singleton(); private Singleton(){ System.out.println("singleton init..."); } public static Singleton getInstance(){ return instance; }}
这是单例模式最简单的实现形式,在内部实例化一个私有成员变量instance,其他的类通过公有静态方法getInstance()来获取该实例。至于为什么叫饿汉式,可以理解为该单例类比较“饿”,所以不管三七二十一先new一个实例出来再说。
饱汉式
在饿汉式单例模式中,由于instance是static静态变量,所以当JVM一加载此类时,该单例对象(instance)就会被创建,这样其实是不好的,假设该单例创建的过程非常耗时,而这个单例类大部分情况下是不会用到的,那么这样就是一种很不好的实现方式。我们更希望的是当用到这个单例类实例时,才去创建它,即达到延迟加载的效果。实现方式如下:
public class LazySingleton { private static LazySingleton instance = null; private LazySingleton(){ System.out.println("singleton init..."); } public static synchronized LazySingleton getInstance(){ if(instance == null){ instance = new LazySingleton(); } return instance; }}
在饱汉式单例模式中,我们先将instance设置为null,然后在getInstance中判断instance是否为null,如果不为null,则实例化该对象,然后返回。这样就实现了延迟加载,当真正需要用到instance时才会去创建。同时要注意,getInstance此时必须是同步的,需要synchronized,否则在多线程环境下,第一个线程正在创建单例,在创建的过程中,第二个线程进来了,此时instance依旧是null,然后第二个线程也进入了if语句块,这样就可能会导致多个实例产生。为什么这个要叫饱汉式呢,可以理解为程序很“饱”,不需要一来就创建,所以创建之前先判断一下是否为null,为null的时候再创建。
内部类式
在饱汉式单例模式中,由于我们加上了同步关键字synchronized,显然会损失掉一定的性能,那么还有没有更好的方式呢?我们可以继续改进,使用内部类的方式,如下:
public class InnerSingleton { private InnerSingleton(){ System.out.println("singleton init..."); } private static class SingletonHolder{ private static InnerSingleton instance = new InnerSingleton(); } public static InnerSingleton getInstance(){ return SingletonHolder.instance; }}
在这种实现中,当InnerSingleton 被加载时,其内部类SingletonHolder不会被初始化,而当getInstance被调用时,才会加载SingletonHolder,从而初始化单例类InnerSingleton。这样即可以实现延迟加载,同时也解决了多线程同步的问题。
适用场景
- 系统只需要一个实例对象
- 客户端调用该实例只允许使用一个公共访问点
总结
单例模式是较为简单的设计模式,但也是很常见也很常用的一种模式。一共有饱汉式、饿汉式、内部类这三种实现方式,我们最佳的实现方式就是内部类式,既实现了延迟加载,同时也支持多线程,所以我们会使用这一种其实就够了,饱汉式、饿汉式有个印象即可。
- 设计模式之----创建型模式(三)-----单例模式
- 设计模式 创建型模式之单例模式
- 设计模式之创建型模式---单例模式
- Java设计模式之创建型模式--单例模式
- 设计模式之创建型模式(1)--单例模式
- 设计模式-创建型模式之 Singleton(单例)
- java设计模式(创建型)之单例模式
- 【小话设计模式】创建型之单例模式
- 设计模式之单例模式(创建型)
- 设计模式(创建型)之单例模式(Singleton Pattern)
- 设计模式-创建型之单例模式
- 创建型:设计模式之单例模式(三)
- 【设计模式】创建型模式之单例Singleton
- JAVA设计模式之单例模式(创建型)
- 《Android之大话设计模式》--设计模式 创建型模式 第四章:单例模式
- 设计模式-创建型模式-单例
- 创建型设计模式-----单例模式
- 创建型设计模式-单例模式
- HDU 4700 Flow(瓶颈生成树)
- AES 加密位: 128位,加密模式:CBC, 填充模式:Zeros
- 用python在mysql中一次创建多个表
- 初学Java面向对象学习笔记
- Mac快捷键
- 设计模式-创建型之单例模式
- 大一:呐喊!却没喊对地方
- Java静态方法间接赋值赋值非静态变量
- java的poi技术读取和导入Excel
- Leetcode 136 Single Number 仅出现一次的数字
- Ubuntu完全教程
- 线索二叉树
- 迪杰斯特拉(最短路径)
- linux线程相关小结