设计模式-单例模式

1、概述

单例模式是一种创建型模式,它要保证一个类仅有一个实例,并提供一个访问它的全局访问点。

2、优缺点

优点:由于单例模式只生成了一个实例,所以能够节约系统资源,减少性能开销,提高系统运行效率。
缺点:因为系统中只有一个实例,导致了单例类的职责过重,违背了“单一职责原则”,同时不利于扩展。

3、实现方式

常见的单例模式实现方式有五种:饿汉式、懒汉式、双重检测锁、静态内部类和枚举单例。

饿汉式

public class SingletonDemo{
    //私有实例,类初始化即加载  
    private static SingletonDemo instance = new SingletonDemo();  
    //构造方法私有化
    private SingletonDemo(){}
    //类的唯一出口
    public static SingletonDemo  getInstance(){
       return instance;      
    } 
}

1. 类加载时就初始化,浪费内存,不能延迟加载;
2. 基于 classloader 机制避免了多线程的同步问题,线程安全;
3. 没有加锁,调用效率高。

懒汉式

//版本1
public class SingletonDemo{
    //定义私有对象为null,先不实例
    private static SingletonDemo instance = null;
    //构造方法私有化
    private SingletonDemo(){}
    //在对外暴露的方法中实例化对象   
    public static SingletonDemo getInstance(){
        if instance == null{
            instance = new SingletonDemo()
        }
        return instance;
    }
}
//可以延迟加载,但是线程不安全

//版本2
public class SingletonDemo{
    //定义私有对象为null,先不实例
    private static SingletonDemo instance = null;
    //构造方法私有化
    private SingletonDemo(){}
    //在对外暴露的方法中实例化对象   
    public synchronized static SingletonDemo getInstance(){
        if instance == null{
            instance = new SingletonDemo()
        }
        return instance;
    }
}
//可以延迟加载,并且线程安全,但是效率不高

//版本3
public class SingletonDemo{
    //volatile修饰,禁止指令重拍,为了后续线程安全
    private volatile static SingletonDemo instance = null;
    //构造方法私有化
    private SingletonDemo(){}
    //在对外暴露的方法中实例化对象   
    public static SingletonDemo getInstance(){
        if instance == null{
            synchronized SingletonDemo.class{
                if instance == null{
                    instance = new SingletonDemo()
                }
            }          
        }
        return instance;
    }
}
//延迟加载,线程安全,效率较高

静态内部类

public class SingletonDemo{
    //静态内部类,调用时才会加载
    private static class InnerClass{
        private final static SingletonDemo INSTANCE = new  SingletonDemo()
    }
    //构造方法私有化
    private SingletonDemo(){}
    //直接获取实例
    public SingletonDemo getInstance(){
        return InnerClass.INSTANCE
    }
}

1. 利用了classloader机制来保证初始化 instance 时只有一个线程,线程安全;
2. 只有通过显式调用 getInstance 方法时,才会显式装载静态内部类,从而实例化instance,延迟加载。

枚举

public enum SingletonDemo{
    INSTANCE;
}

枚举:天生就是单例最佳。但是实际工作使用中,很少使用。
1.简洁,无线程安全问题
2.自动支持序列化机制,自动防止反序列化重新创建新的对象,绝对防止多次实例化。
3.不是延迟加载的。

4、应用场景

1、生成全局惟一的序列号;
2、访问全局复用的惟一资源,如磁盘、总线等;
3、单个对象占用的资源过多,如数据库等;
4、系统全局统一管理,如Windows下的Task Manager;
5、网站计数器。

This entry was posted in 应用, 设计模式. Bookmark the permalink.