单例设计模式

单例设计模式

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

写一个单例设计模式的一般步骤分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());
        }
    }
}
相关推荐
古月居GYH2 分钟前
在C++上实现反射用法
java·开发语言·c++
吾与谁归in21 分钟前
【C#设计模式(13)——代理模式(Proxy Pattern)】
设计模式·c#·代理模式
吾与谁归in22 分钟前
【C#设计模式(14)——责任链模式( Chain-of-responsibility Pattern)】
设计模式·c#·责任链模式
闲人一枚(学习中)29 分钟前
设计模式-创建型-原型模式
设计模式
儿时可乖了1 小时前
使用 Java 操作 SQLite 数据库
java·数据库·sqlite
ruleslol1 小时前
java基础概念37:正则表达式2-爬虫
java
Iced_Sheep1 小时前
干掉 if else 之策略模式
后端·设计模式
xmh-sxh-13141 小时前
jdk各个版本介绍
java