单例设计模式

单例设计模式

所谓单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例。

写一个单例设计模式的一般步骤分3步:

  • 私有化构造器
  • 定义一个类变量记住类的一个对象
  • 设计一个对外的共有方法来获取这个实例对象

Runtime类就是一个典型的单例设计模式

单例模式有8种实现方法
1. 饿汉式(静态常量)
2. 饿汉式(静态代码块)

  1. 懒汉式(线程不安全)

  2. 懒汉式(同步方法,线程安全)

  3. 懒汉式(同步代码块,线程不安全)
    **6. 双重检查(线程安全)

  4. 静态内部类

  5. 枚举**

1、饿汉式(静态常量)

java 复制代码
class Singleton{
    //构造器私有化
    private Singleton(){

    }
    //本类内部创建实例对象 为什么需要static修饰?因为这是类变量
    private final static Singleton instance = new Singleton();

    //提供一个静态方法,返回实例对象
    public static Singleton getInstance(){
        return instance;
    }
}

2、饿汉式(静态代码块)

java 复制代码
class Singleton{
    //构造器私有化
    private Singleton(){
    }

    private static Singleton instance ;

    //在静态代码块中创建实例对象 why? 因为静态代码块只会被执行一次
    static {
        instance = new Singleton();
    }

    //提供一个静态方法,返回实例对象
    public static Singleton getInstance(){
        return instance;
    }
}

3、懒汉式(线程不安全)

在调用getInstance()方法的时候才会被创建实例对象

java 复制代码
class Singleton{
    private static Singleton instance;
    //构造器私有化
    private Singleton(){

    }

    //提供一个静态的公有方法,当使用到该方法的时候,才去创建instance
    //懒汉式
    public static Singleton getInstance(){
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

4、懒汉式(同步方法,线程安全)

java 复制代码
class Singleton{
    private static Singleton instance;
    //构造器私有化
    private Singleton(){

    }

    //提供一个静态的公有方法,当使用到该方法的时候,才去创建instance
    //懒汉式(同步方法)
    public static synchronized Singleton getInstance(){
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

5、懒汉式(同步代码块,线程不安全)

java 复制代码
class Singleton{
    private static Singleton instance;
    //构造器私有化
    private Singleton(){

    }

    //提供一个静态的公有方法,当使用到该方法的时候,才去创建instance
    //懒汉式(同步代码块)
    public static Singleton getInstance(){
        if (instance == null){
            synchronized (Singleton.class){
                instance = new Singleton();
            }
        }
        return instance;
    }
}

6、双重检查(线程安全)

java 复制代码
class Singleton{
    private static volatile Singleton instance;
    //构造器私有化
    private Singleton(){

    }

    //提供一个静态的公有方法,当使用到该方法的时候,才去创建instance
    //加入双重检查代码,解决线程安全问题,同时解决懒加载问题
    public static Singleton getInstance(){
        if (instance == null){
            synchronized (Singleton.class){
                if (instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

7、静态内部类

java 复制代码
class Singleton{
    //构造器私有化
    private Singleton(){

    }
    //写一个静态内部类,该类中有一个静态属性Singleton
    //1、在Singleton被装载的时候,这个静态内部类不会被装载
    //2、当调用getInstance装载SingletonInstance的时候,只会被执行一次
    private static class SingletonInstance{
        private static final Singleton instance= new Singleton();
    }

    //提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
    public static synchronized Singleton getInstance(){
        return SingletonInstance.instance;
    }
}

8、枚举

java 复制代码
//使用枚举,可以实现单例
enum Singleton{
    INSTANCE;
    public void sayOK(){
        System.out.println("ok~");
    }
}

根据上面的描述,写卡码网的购物车案例

https://kamacoder.com/problempage.php?pid=1074

首先创建一个商品类

java 复制代码
//需要一个商品类
class Spu{
    private String spuName;
    private int spuNum;

    public Spu() {
    }

    public Spu(String spuName, int spuNum) {
        this.spuName = spuName;
        this.spuNum = spuNum;
    }

    public String getSpuName() {
        return spuName;
    }

    public int getSpuNum() {
        return spuNum;
    }
}

下面的购物车类使用单例模式:

1、饿汉式(静态常量)

java 复制代码
//使用饿汉式创建一个购物车类
class Cart{
    private final List<Spu> spuList;
    //私有化构造器
    private Cart(){
        spuList = new ArrayList<>();
    }

    //本类内部创建实例对象
    private final static Cart instance = new Cart();

    //提供一个静态方法,返回实例对象
    public static Cart getInstance(){
        return instance;
    }
    public void addSpu(String spuName, int spuNum){
        Spu spu = new Spu(spuName,spuNum);
        this.spuList.add(spu);
    }
    
    public void printSpuList(){
        for (Spu spu :
                spuList) {
            System.out.println(spu.getSpuName()+" "+spu.getSpuNum());
        }
    }
}

2、饿汉式(静态代码块)

java 复制代码
//使用饿汉式创建一个购物车类
class Cart{
    private final List<Spu> spuList;
    //私有化构造器
    private Cart(){
        spuList = new ArrayList<>();
    }

    //本类内部创建实例对象
    private final static Cart instance;

    //使用静态代码块创建实例对象
    static {
        instance = new Cart();
    }

    //提供一个静态方法,返回实例对象
    public static Cart getInstance(){
        return instance;
    }
    public void addSpu(String spuName, int spuNum){
        Spu spu = new Spu(spuName,spuNum);
        this.spuList.add(spu);
    }
    
    public void printSpuList(){
        for (Spu spu :
                spuList) {
            System.out.println(spu.getSpuName()+" "+spu.getSpuNum());
        }
    }
}

3、懒汉式(线程不安全)

java 复制代码
class Cart{
    private final List<Spu> spuList;
    //私有化构造器
    private Cart(){
        spuList = new ArrayList<>();
    }

    //本类内部创建实例对象
    private static Cart instance;

    //提供一个静态方法,返回实例对象
    //在调用getinstance的时候 才会去创建一个对象
    public static Cart getInstance(){
        if (instance == null){
            instance = new Cart();
        }
        return instance;
    }
    public void addSpu(String spuName, int spuNum){
        Spu spu = new Spu(spuName,spuNum);
        this.spuList.add(spu);
    }
    
    public void printSpuList(){
        for (Spu spu :
                spuList) {
            System.out.println(spu.getSpuName()+" "+spu.getSpuNum());
        }
    }
}

4、懒汉式(同步方法)

java 复制代码
class Cart{
    private final List<Spu> spuList;
    //私有化构造器
    private Cart(){
        spuList = new ArrayList<>();
    }

    //本类内部创建实例对象
    private static Cart instance;

    //提供一个静态方法,返回实例对象
    //在调用getinstance的时候 才会去创建一个对象
    //使用同步方法
    public static synchronized Cart getInstance(){
        if (instance == null){
            instance = new Cart();
        }
        return instance;
    }
    public void addSpu(String spuName, int spuNum){
        Spu spu = new Spu(spuName,spuNum);
        this.spuList.add(spu);
    }
    
    public void printSpuList(){
        for (Spu spu :
                spuList) {
            System.out.println(spu.getSpuName()+" "+spu.getSpuNum());
        }
    }
}

5、懒汉式(同步代码块)

java 复制代码
class Cart{
    private final List<Spu> spuList;
    //私有化构造器
    private Cart(){
        spuList = new ArrayList<>();
    }

    //本类内部创建实例对象
    private static Cart instance;

    //提供一个静态方法,返回实例对象
    //在调用getinstance的时候 才会去创建一个对象
    //使用同步代码块
    public static Cart getInstance(){
        if (instance == null){
            synchronized (Cart.class){
                instance = new Cart();
            }
        }
        return instance;
    }
    public void addSpu(String spuName, int spuNum){
        Spu spu = new Spu(spuName,spuNum);
        this.spuList.add(spu);
    }
    
    public void printSpuList(){
        for (Spu spu :
                spuList) {
            System.out.println(spu.getSpuName()+" "+spu.getSpuNum());
        }
    }
}

6、双重检查

java 复制代码
class Cart{
    private final List<Spu> spuList;
    //私有化构造器
    private Cart(){
        spuList = new ArrayList<>();
    }

    private volatile static Cart instance;

    public static Cart getInstance(){
        if (instance == null){
            synchronized (Cart.class){
                if (instance == null){
                    instance = new Cart();
                }
            }
        }
        return instance;
    }

    public void addSpu(String spuName, int spuNum){
        Spu spu = new Spu(spuName,spuNum);
        this.spuList.add(spu);
    }
    
    public void printSpuList(){
        for (Spu spu :
                spuList) {
            System.out.println(spu.getSpuName()+" "+spu.getSpuNum());
        }
    }
}

7、静态内部类

java 复制代码
class Cart{
    private final List<Spu> spuList;
    //私有化构造器
    private Cart(){
        spuList = new ArrayList<>();
    }

    //创建一个静态内部类
    private static class Instance{
        private final static Cart INSTANCE = new Cart();
    }

    //提供一个静态方法,返回实例对象
    public static Cart getInstance(){
        return Instance.INSTANCE;

    }
    public void addSpu(String spuName, int spuNum){
        Spu spu = new Spu(spuName,spuNum);
        this.spuList.add(spu);
    }
    
    public void printSpuList(){
        for (Spu spu :
                spuList) {
            System.out.println(spu.getSpuName()+" "+spu.getSpuNum());
        }
    }
}
相关推荐
七星静香7 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员8 分钟前
java导出word文件(手绘)
java·开发语言·word
ZHOUPUYU8 分钟前
IntelliJ IDEA超详细下载安装教程(附安装包)
java·ide·intellij-idea
stewie612 分钟前
在IDEA中使用Git
java·git
Elaine20239127 分钟前
06 网络编程基础
java·网络
G丶AEOM28 分钟前
分布式——BASE理论
java·分布式·八股
落落鱼201329 分钟前
tp接口 入口文件 500 错误原因
java·开发语言
想要打 Acm 的小周同学呀30 分钟前
LRU缓存算法
java·算法·缓存
镰刀出海33 分钟前
Recyclerview缓存原理
java·开发语言·缓存·recyclerview·android面试
阿伟*rui3 小时前
配置管理,雪崩问题分析,sentinel的使用
java·spring boot·sentinel