单例设计模式

单例设计模式

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

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

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

Runtime类就是一个典型的单例设计模式
在这里插入图片描述

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

3. 懒汉式(线程不安全)
4. 懒汉式(同步方法,线程安全)
5. 懒汉式(同步代码块,线程不安全)
6. 双重检查(线程安全)
7. 静态内部类
8. 枚举

1、饿汉式(静态常量)

class Singleton{
    //构造器私有化
    private Singleton(){

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

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

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

class Singleton{
    //构造器私有化
    private Singleton(){
    }

    private static Singleton instance ;

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

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

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

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

class Singleton{
    private static Singleton instance;
    //构造器私有化
    private Singleton(){

    }

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

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

class Singleton{
    private static Singleton instance;
    //构造器私有化
    private Singleton(){

    }

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

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

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、双重检查(线程安全)

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、静态内部类

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、枚举

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

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

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

首先创建一个商品类

//需要一个商品类
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、饿汉式(静态常量)

//使用饿汉式创建一个购物车类
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、饿汉式(静态代码块)

//使用饿汉式创建一个购物车类
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、懒汉式(线程不安全)

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、懒汉式(同步方法)

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、懒汉式(同步代码块)

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、双重检查

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、静态内部类

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());
        }
    }
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值