单例设计模式

单例设计模式

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

写一个单例设计模式的一般步骤分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());
        }
    }
}
相关推荐
mghio7 小时前
Dubbo 中的集群容错
java·微服务·dubbo
千千寰宇8 小时前
[设计模式/Java/多线程] 设计模式之单例模式【9】
设计模式·操作系统-进程/线程/并发
咖啡教室12 小时前
java日常开发笔记和开发问题记录
java
咖啡教室12 小时前
java练习项目记录笔记
java
鱼樱前端13 小时前
maven的基础安装和使用--mac/window版本
java·后端
RainbowSea13 小时前
6. RabbitMQ 死信队列的详细操作编写
java·消息队列·rabbitmq
RainbowSea13 小时前
5. RabbitMQ 消息队列中 Exchanges(交换机) 的详细说明
java·消息队列·rabbitmq
李少兄15 小时前
Unirest:优雅的Java HTTP客户端库
java·开发语言·http
此木|西贝15 小时前
【设计模式】原型模式
java·设计模式·原型模式