21-The Singleton Pattern

Download Report

Transcript 21-The Singleton Pattern

Computer Science 209
The Singleton Pattern
Random Numbers
System.out.println((int)(Math.random() * 6) + 1);
System.out.println((int)(Math.random() * 6) + 1);
Math.random() uses a single generator that is seeded at
the startup of the JVM. The seed is calculated as a function
of the computer’s clock
Kind of a pain to use to obtain random integers
java.util.Random
java.util.Random generator = new java.util.Random();
System.out.println(generator.nextInt(6) + 1);
System.out.println(generator.nextInt(6) + 1);
System.out.println(generator.nextDouble());
System.out.println(generator.nextBoolean());
The Random class is much more convenient to use
A Random object is also seeded from the clock
java.util.Random
java.util.Random generator1 = new java.util.Random();
java.util.Random generator2 = new java.util.Random();
System.out.println(generator1.nextInt(6) + 1);
System.out.println(generator2.nextInt(6) + 1);
If distinct Random objects are seeded during the same
millisecond, they will get the same seed and generate the
same pseudo-random sequence
Rolling a Die
import java.util.Random;
public class Die{
private int value;
private Random generator;
public Die(){
value = 0;
generator = new Random();
}
public void roll(){
value = generator.nextInt(6) + 1;
}
public String toString(){
return "" + value;
}
}
Rolling a Die
private Die die1 = new Die();
private Die die2 = new Die();
public DiceApp(){
setTitle("Roll the Dice");
diceField1.setEditable(false);
diceField2.setEditable(false);
rollButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
die1.roll();
die2.roll();
diceField1.setText(die1.toString());
diceField2.setText(die2.toString());
}
});
Container c = getContentPane();
JPanel panel = new JPanel();
panel.add(diceField1);
panel.add(diceField2);
c.add("Center", panel);
c.add("South", rollButton);
}
Two Won’t Work
• The two dice are created within a
millisecond of each other, so their random
number generators produce the same
sequence of numbers
• We need a way of sharing one instance of
Random among all dice
The Context of the
Singleton Pattern
• All clients need to share a single instance of
a class
• No additional instances can be created
accidentally
Solution of the Singleton Pattern
• Define a class with a private constructor
• The class constructs a single instance of itself
• The class includes a static method to return the
single instance
A Better Random
import java.util.Random;
public class SingleRandom{
private static SingleRandom instance = new SingleRandom();
private Random generator;
private SingleRandom(){
generator = new Random();
}
public int nextInt(int limit){
return generator.nextInt(limit);
}
public static SingleRandom getInstance(){
return instance;
}
}
A Better Die
public class BetterDie{
private int value;
private SingleRandom generator;
public BetterDie(){
value = 0;
generator = SingleRandom.getInstance();
}
public void roll(){
value = generator.nextInt(6) + 1;
}
public String toString(){
return "" + value;
}
}
Playing Cards
import javax.swing.*;
public class Card implementsComparable<Card>{
private String suit;
private int rank;
Suits are
strings, but
should not be
just any strings
public Card(String suit, int rank){
this.suit = suit;
this.rank = rank;
}
Card queenOfSpades = new Card("spades", 12);
Card twoOfHearts
= new Card("hearts", 2);
Must check
and throw
exceptions to
enforce proper
use
Define a New Type for Suits
import javax.swing.*;
public class Card implementsComparable<Card>{
private Suit suit;
private int rank;
The type Suit
is restricted to
just 4 values
public Card(Suit suit, int rank){
this.suit = suit;
this.rank = rank;
}
Card queenOfSpades = new Card(Suit.spade, 12);
Card twoOfHearts
= new Card(Suit.heart, 2);
The compiler
enforces their
proper use
public class Suit implements Comparable<Suit>{
static
static
static
static
public
public
public
public
final
final
final
final
Suit
Suit
Suit
Suit
spade
heart
diamond
club
=
=
=
=
new
new
new
new
Suit(4,
Suit(3,
Suit(2,
Suit(1,
"spades");
"hearts");
"diamonds");
"clubs");
private int order;
private String name;
private Suit(int ord, String nm){
name = nm;
order = ord;
}
public int compareTo(Suit other){
return order - other.order;
}
public String toString(){
return name;
}
}
Similar to the singleton,
but has 4 instances
Problem with Decks of Cards
• Every time you create a new deck, the card
images must be reloaded from disk
• If you do this in an applet, they’re reloaded
from a remote Web server
• Decks are mutable, but cards are not
Solution: 52 Singleton Cards
• The Card class maintains a static list of all
cards, which are instantiated just once,
when the first card is instantiated
• When new decks are instantiated, they
receive references to cards in this list
Card queenOfSpades = Card.newInstance(Suit.spade, 12);
Card twoOfHearts
= Card.newInstance(Suit.heart, 2);