CPSC 210

D6: Singleton Pattern

Learning Goals

  • To apply the Singleton Design Pattern to a given problem

Example Motivation

I want to coordinate a state across my system. For this purpose, I create a class for my state.

How do I make sure there is always only one instance of my State class in my system?

public class WifiState {
  private int numberOfClients;
  private int mbDownloadVolume;
  private int mbUploadVolume;
  
  public WifiState() {}
  
  // setters
}
// ...somewhere in code...
// State state = new WifiState();
// state.setNumberOfClients(30);
// ...
// ...somewhere in code...
// How do I get the current state?

The Singleton Pattern

Gang of Four: "Ensure a class only has one instance, and provide a global point of access to it."

Wikipedia: "Design pattern that restricts the instantiation of a class to one 'single' instance. This is useful when exactly one object is needed to coordinate actions across the system."

The Singleton Pattern (2)

public class WifiState {
  private int numberOfClients;
  private int mbDownloadVolume;
  private int mbUploadVolume;
  
  public WifiState() {}
  
  // setters
}
public class WifiState {
  private static WifiState INSTANCE;

  private int numClients = 0;
  private int mbDownloadRate = 0;
  private int mbUploadRate = 0;

  private WifiState() {}

  public static WifiState getInstance() {
    if (INSTANCE == null) {
      INSTANCE = new WifiState();
    }
    return INSTANCE;
  }
}

Lecture Ticket

public class Unique {
    private static Unique singleton = new Unique();
    
    public static Unique getInstance() {
        return singleton;
    }
    
    private String pithyStatement = "original";
    private int quoteCount = 0;
    
    private Unique() { }
    
    public String quote() {
        quoteCount++;
        return pithyStatement;
    }
    
    public void setPithyStatement(String stmt) {
        pithyStatement = stmt;
    }
    
    public int getQuoteCount() {
        return quoteCount;
    }
}
// REQUIRES: u.getQuoteCount() == 0.
public void manipulate(Unique u) {
    Unique u1 = u;
    Unique u2 = Unique.getInstance();
    
    System.out.println(u.quote());
    if (u2 == u1) {
        u2.setPithyStatement("clone");
    }
    System.out.println(u1.quote());
    if (u2.quote().equals(u.quote())) { 
        u1.setPithyStatement("question");
    }
    System.out.println(u.quote());
    System.out.println(u1.quote());
    System.out.println(u2.quote());
    System.out.println(u.getQuoteCount());
    System.out.println(u1.getQuoteCount());
    System.out.println(u2.getQuoteCount());
}

What will a correct call to manipulate print, in order?

Example: We already seen it!

The Alarm System!

Let's have a look...

/**
 * Represents a log of alarm system events.
 * We use the Singleton Design Pattern to ensure that there is only
 * one EventLog in the system and that the system has global access
 * to the single instance of the EventLog.
 */
public class EventLog implements Iterable<Event> {

If you want to dig deeper...

  • We could also implement a global state as a static class

If you want to dig deeper...

Lecture Lab

Highlander (THE ONE HIGHLANDER):
        />___________________________________
[########[]_________________________________/
        />
Highlander (THE ONE HIGHLANDER):
        />___________________________________
[########[]_________________________________/
        />

Desired Output

Highlander (Joe's Highlander):
        />___________________________________
[########[]_________________________________/
        />
Highlander (Sue's Highlander):
        />___________________________________
[########[]_________________________________/
        />

Actual Output

  • Joe and Sue are playing the Highlander game
  • But there are multiple Highlanders

D6: Singleton Pattern

The End - Thank You!

CPSC210 - D6: Singleton

By Steven Wolfman

CPSC210 - D6: Singleton

  • 180