
GOF四人合著出版了一本名为Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素)的书,共有23种设计模式,而这些设计模式又分为3大类:
1、创建型模式
2、结构型模式
3、行为型模式
单例模式属于第一种,是创建型模式
什么是单例模式呢?what?
答:顾名思义,就是单一的一个实例(只有一个对象)的模式
为什么只需要一个实例,有个鸟用?
答:一个全局使用的类频繁的创建与销毁,浪费时间,消耗资源。
有鸟用啊,当我们想控制一个类的实例数目,节省系统资源的时候。
那它是怎么做到只有一个实例的呢?
我们知道,构造器是用来创建对象的(实例化),我们只需要让该类的构造器私有

应用的实例:
一个班级只有一个班主任,一个帝国只有一个国王。
Windows系统是多进程多线程的,在操作一个文件的时候,就不可避免多个进程或者多个进程同时操作这一个文件对象,所以所有文件的处理必须通过唯一的实例来进行。
优点:只有一个实例,减少内存的开销,频繁的创建和销毁实例。
缺点:没有接口,不能继承。
使用场景:
Java中的IO与数据流的连接等。
几种实现方式:
1、懒汉式(lazy loading),线程不安全(没有用synchronized修饰那个得到的方法)
很懒,很懒,很懒,这种实现的方式就是不支持多线程。严格意义他不是单例模式
第一次调用getInstance()的时候才去创建那个单例对象
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}我们来看加锁的,加了synchronized
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}虽然支持了多线程,但是加锁会影响效率,
2、饿汉式
很饥渴、很饥渴、很饥渴
比较常用的方式,不调用getInstance()方法就已经有对象,所以容易产生垃圾对象。
缺点:类加载的时候就初始化,浪费内存。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}3、双重校验锁(双重保险)
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}使用synchronized锁住了代码块,如果为空则判断是否有线程持有该锁,则等待,不为空则直接返回这个单例对象。
4、使用静态内部类来实现
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}Java里面static一般用来修饰成员变量或函数。但有一种特殊用法是用static修饰内部类,普通类是不允许声明为静态的,只有内部类才可以。
被static修饰的内部类可以直接作为一个普通类来使用,而不需实例一个外部类
需要注意的是当一个内部类没有使用static修饰的时候,是不能直接使用内部类创建对象,须要先使用外部类对象点new内部类对象及(外部类对象.new 内部类())
5、枚举
这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
用这种方式写不免让人感觉生疏,在实际工作中,也很少用。
经验之谈:
不建议使用懒汉式,建议使用饿汉式,很饥渴,很饥渴,很饥渴的那种,
只有在要明确实现 lazy loading 效果时,才会使用第 5 种登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式。
以上学习来自菜鸟教程。
单例模式 | 菜鸟教程www.runoob.com
本文详细介绍了单例模式的概念及其在软件开发中的应用。探讨了单例模式的多种实现方式,包括懒汉式、饿汉式、双重校验锁、静态内部类及枚举方式,并分析了各自的优缺点。
508

被折叠的 条评论
为什么被折叠?



