【设计模式】单例模式篇

目录

Singleton Pattern

1、定义

2、比喻了解

3、代码示例

4、高频问题


Singleton Pattern

1、定义

当你需要确保一个类只有一个实例,并且希望全局访问这个实例时,可以使用单例模式。在单例模式中,一个类只有一个实例,并且该实例可以被全局访问

实现单例模式的一种常见方法是使用一个私有构造函数、一个私有静态变量和一个公共静态方法来创建和返回该实例。私有构造函数确保其他代码无法实例化该类,而私有静态变量存储该类的唯一实例。公共静态方法允许其他代码获取该实例,并在第一次调用时创建它。

2、比喻了解

当你去餐厅吃饭时,你点了一份特别美味的菜,但是这道菜只有一份,如果你的朋友也想尝尝,那么服务员可以将这道菜分成两份,并且每个人都能品尝到同样的美味。

换句话说,在这个例子中,这道菜就像一个单例对象,因为它只有一个实例。无论你多少次点这道菜,你都会得到同样的一份。在这种情况下,服务员充当了一个类似于单例模式的角色,负责创建和管理该对象的实例,以确保客人们得到的都是同一份菜。

3、代码示例

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

在上面的示例中,Singleton 类具有一个私有构造函数,这意味着其他类无法使用 new 操作符来创建该类的实例。此外,Singleton 类还具有一个名为 instance 的私有静态变量,它存储了唯一的 Singleton 实例。

getInstance() 方法是一个公共静态方法,它允许其他类获取 Singleton 的唯一实例。如果 instance 变量为 null,则方法将创建一个新的 Singleton 实例并将其分配给 instance 变量。否则,方法将直接返回 instance 变量。

请注意,在上面的示例中,getInstance() 方法使用了一种称为“懒汉式”单例模式的实现方式。这种实现方式延迟了 Singleton 实例的创建时间,而不是在类加载时立即创建该实例。这是因为如果实例从未被使用,则在类加载时创建它可能会浪费系统资源。

let instance = null;

class Singleton {
  constructor() {
    if (!instance) {
      instance = this;
    }

    return instance;
  }

  logMessage(message) {
    console.log(message);
  }
}

const singletonInstance1 = new Singleton();
const singletonInstance2 = new Singleton();

console.log(singletonInstance1 === singletonInstance2); // Output: true

singletonInstance1.logMessage("Hello, world!"); // Output: "Hello, world!"
singletonInstance2.logMessage("Same instance!"); // Output: "Same instance!"

在上面的示例中,我们定义了一个名为Singleton的类来实现单例模式。 在构造函数中我们先检查变量“instance”是否已经被赋值,如果是,则直接返回该实例;否则,将当前实例赋值给“instance”。

最终,我们创建两个名为singletonInstance1和singletonInstance2的实例。由于它们都是Singleton类的实例,因此它们应该是相等的(即,它们指向同一个对象)。输出结果也证明了这一点。

最后,我们在每个实例上调用logMessage方法,以确保它们确实是同一个对象的实例。

4、高频问题

1)单例模式的定义是什么?

答:单例模式是一种创建型设计模式,它保证一个类只有一个实例,并提供了全局访问该实例的方式。

2)为什么要使用单例模式?可以提供一个实际应用场景吗?

答:单例模式可以避免不必要的内存分配和对象创建,提高程序的性能和效率。此外,单例模式还可以确保系统中某些资源(如数据库连接池)只被一个对象占用,从而避免资源竞争和冲突。一个常见的实际应用场景是日志记录器,由于多个线程同时写入日志文件容易出现冲突,因此可以使用单例模式来确保所有线程共享同一个日志记录器实例。

3)单例模式如何实现?可以给出一个基本的实现示例代码吗?

答:单例模式可以通过一个私有构造函数、一个私有静态变量和一个公共静态方法来实现。以下是一个基本的实现

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

4) 如果需要创建线程安全的单例对象,应该怎么做?

答:为了创建线程安全的单例对象,可以使用双重检查锁定或静态内部类的方式。在使用双重检查锁定时,需要将 getInstance() 方法添加同步锁以确保只有一个线程能够访问该方法。在使用静态内部类时,由于 JVM 在加载类时会保证线程安全,因此可以避免同步锁的开销。

​​​​​​​// 使用双重检查锁定实现线程安全的单例模式
public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {}

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

// 使用静态内部类实现线程安全的单例模式
public class Singleton {
    private Singleton() {}

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

5) 单例模式有哪些优缺点?如何权衡这些优缺点?

答:单例模式的优点包括:

  • 可以避免不必要的内存分配和对象创建,提高程序的性能和效率。
  • 可以确保系统中某些资源(如数据库连接池)只被一个对象占用,从而避免资源竞争和冲突。

单例模式的缺点包括:

  • 可能会导致程序结构复杂化。
  • 单例模式在多线程环境下可能会引发一些问题,例如:线程安全性、可测试性等。

在权衡这些优缺点时,需要考虑具体的业务场景和应用需求,以及是否真正需要使用单例模式。如果确实需要使用单例模式,可以通过合适的实现方式来解决其缺点,并确保系统的可靠性和稳定性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值