在开发过程中,遇到了一个业务需求,即需要实现点餐后打印有序的单号。这个需求需要在线上和线下的点餐系统中共用,并且每天在第二天更新时,单号需要从0开始重新计数。解决这个需求需要解决的是线上与线下共享一组数字以及第二天更新的问题。
对于线上线下共享问题,因为属于俩个接口,我就想到了创建一个公共类,在公共类中定义次数属性每调用点餐接口时调用此公共类中的方法,将次数加一并返回当前次数值,但在使用时发现接口每次调用都会重新创建新的对象从而刷新次数,至此就想到了单例模式。
单例模式是一种创建型设计模式,用于确保类只有一个实例,并提供全局访问点。它通过限制类的实例化过程,使得该类在任何时候只能有一个对象存在。
确保类只有一个实例就保证在使用的时候不会出现刷新次数的问题,提供全局访问点可以让我们在线上和线下个接口都可以使用到,很好的解决了遇到的业务需求,当然解决方法有很多这只是其中一种。
我们详细来说说单例模式:
-
私有化构造方法(Private Constructor):单例类的构造方法被私有化,这样外部就无法通过
new
操作符实例化该类。 -
静态变量持有实例(Static Variable Holding Instance):单例类内部维护一个静态变量,用于保存单例对象的实例。
-
静态方法获取实例(Static Method for Instance Access):单例类提供一个静态方法,用于获取单例对象的实例。这个方法通常被命名为
getInstance()
。 -
懒加载(Lazy Initialization):单例对象在第一次被使用时进行实例化,而不是在单例类加载时就创建。
-
线程安全(Thread Safety):确保多线程环境下获取单例对象的实例是线程安全的,避免出现多个实例。
下面是一个懒加载方式实现的线程安全的单例模式示例:
public class Singleton{
private static Singleton instance;
private Singletion(){
//私有化构造
}
public static synchronized Singleton getInstance(){
if(instance == null){
instance =new Singletion();
}
return instance;
}
}
解释一下:
在上述示例中,Singleton
类的构造方法被私有化,确保外部无法直接实例化该类。getInstance()
方法使用了懒加载的方式,第一次调用时才会实例化单例对象。
在getInstance()
方法中,通过检查instance
变量是否为空来判断单例对象是否已经被实例化。如果为空,则创建一个新的实例;如果不为空,则直接返回现有的实例。
由于getInstance()
方法是同步的,即使用了synchronized
关键字,可以确保在多线程环境下获取单例对象的实例是线程安全的。
最后对于单例模式,它适用于需要全局唯一实例的场景,例如我开发中遇到的那个问题又例如数据库连接池、日志记录器等。它可以节省系统资源,并确保在多个地方使用同一个实例,避免了对象的重复创建和管理。但是,过度使用单例模式可能导致代码的耦合性增加,使得代码难以进行测试和维护,因此在使用单例模式时需要慎重考虑。
最后的最后放一下解决上述业务需求所写的类
import java.time.LocalDate;
public class APICounter {
private static APICounter instance;
private int calls;
private LocalDate today;
private APICounter() {
resetCounter();
}
public static synchronized APICounter getInstance() {
if (instance == null) {
instance = new APICounter();
}
return instance;
}
//重置方法
public void resetCounter() {
calls=0;
today = LocalDate.now();
}
public int incrementCounter() {
LocalDate currentDate = LocalDate.now();
//对比是否为同一天
if (!currentDate.equals(today)) {
resetCounter();
}
calls++;
return calls;
}
}