Skip to content

Singleton Pattern Guide

Exactly one instance, reachable from everywhere

Builds on static and final

Stage 3core1 min read

1. No Global State Guarantee

JudgeAnalytics is a plain class. Any code can create one with new JudgeAnalytics().

  • The Issue: Each caller gets its own instance. Run counts and submit counts end up spread across different objects.
  • The Impact: No one object knows the "total runs" or "total submits" for the whole system. One component may see 5 runs while another sees 2, depending on which instance it holds.

2. No Single Place for "Global" Data

Analytics that describe the whole system (e.g., total submissions to a judge) should keep that state in exactly one place.

  • The Issue: The design allows any number of instances. Each class that needs analytics creates its own JudgeAnalytics, so the "global" picture is never right.
  • The Impact: Reports, dashboards, or rate limits that need total run/submit counts have no single source of truth to read.

3. Wasted Resources and Inconsistency

Creating a new JudgeAnalytics in every service or controller leads to:

  • The Issue: Extra objects that each keep their own counters. Nothing links them.
  • The Scenario: Main (or several services) each call new JudgeAnalytics(). A click counted in one place does not show up in another. You cannot answer "how many runs happened in total?".

4. Testing and Predictability

With many instances, tests and production code have no shared state to rely on.

  • The Issue: You cannot pass in "the" analytics object (inject it) or check a global count, because no single instance exists.
  • The Impact: System-wide metrics are harder to test and to reason about.

Summary of the "Smell"

Some classes must be one system-wide resource (logger, config, connection pool, or global analytics). If anyone can still call new on them, make them a Singleton. Then only one instance ever exists, and all callers share it.

In this topic

Before code1 file

Before/Main.java56 linesGitHub
package DesignPatterns.CreationalPatterns.SingletonDesignPattern.Before;/** * PROBLEM: JudgeAnalytics is a plain class. Anyone can create multiple instances. * Each instance has its own run/submit counts — there is no single source of truth. */class JudgeAnalytics {    private int run = 0;    private int submit = 0;    public void countRun() {        run++;    }    public void countSubmit() {        submit++;    }    public int getRunCount() {        return run;    }    public int getSubmitCount() {        return submit;    }}/** * PROBLEM: Main (and any other class) creates its own JudgeAnalytics. * If another service also does "new JudgeAnalytics()", we now have two separate * analytics objects. Counts are not shared; there is no global view. */class Main {    public static void main(String[] args) {        JudgeAnalytics analytics1 = new JudgeAnalytics();        JudgeAnalytics analytics2 = new JudgeAnalytics();        analytics1.countRun();        analytics1.countRun();        analytics2.countSubmit();        // Each instance has different counts. "Global" totals do not exist.        System.out.println("analytics1 runs: " + analytics1.getRunCount()); // 2        System.out.println(            "analytics1 submits: " + analytics1.getSubmitCount()        ); // 0        System.out.println("analytics2 runs: " + analytics2.getRunCount()); // 0        System.out.println(            "analytics2 submits: " + analytics2.getSubmitCount()        ); // 1        // No way to get "total runs = 2, total submits = 1" from a single object.    }}

Done with this topic?

How well do you know it?