单例设计模式

单例设计模式

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

写一个单例设计模式的一般步骤分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());
        }
    }
}
相关推荐
学java的小菜鸟啊15 分钟前
第五章 网络编程 TCP/UDP/Socket
java·开发语言·网络·数据结构·网络协议·tcp/ip·udp
zheeez19 分钟前
微服务注册中⼼2
java·微服务·nacos·架构
程序员-珍23 分钟前
SpringBoot v2.6.13 整合 swagger
java·spring boot·后端
徐*红30 分钟前
springboot使用minio(8.5.11)
java·spring boot·spring
聆听HJ31 分钟前
java 解析excel
java·开发语言·excel
AntDreamer34 分钟前
在实际开发中,如何根据项目需求调整 RecyclerView 的缓存策略?
android·java·缓存·面试·性能优化·kotlin
java_heartLake39 分钟前
设计模式之建造者模式
java·设计模式·建造者模式
G皮T39 分钟前
【设计模式】创建型模式(四):建造者模式
java·设计模式·编程·建造者模式·builder·建造者
niceffking43 分钟前
JVM HotSpot 虚拟机: 对象的创建, 内存布局和访问定位
java·jvm
菜鸟求带飞_1 小时前
算法打卡:第十一章 图论part01
java·数据结构·算法