- Java Design Patterns: Singleton vs Utility Classes

Singleton vs utility class
at first glance, the singleton pattern does not seem to
offer any advantages to using a utility class
i.e., a utility class with non-final static fields looks a lot like
a single object with non-static fields
there is a fundamental difference between a singleton
and a utility class:
a singleton represents an object whereas a utility is a class
1
Singleton vs utility class
suppose that you want your singleton/utility class to
implement an interface
up to and including Java 7, a utility class could not
implement an interface
a singleton can freely implement interfaces
Java 8 now allows static methods in interfaces
a utility class can now implement an interface that has all
static methods
but a utility class still cannot implement an interface having non-
static methods (such as 
Iterable
)
2
Singleton vs utility class
suppose that you decide later on that you need
multiple instances rather than a singleton/utility class
a utility class cannot be used to create objects of the utility
class type
a singleton can be converted to a non-singleton
3
Singleton vs utility class
can you create a method that has a parameter whose
type is a utility class?
no, a parameter is a variable that stores a reference to an
object and there are no utility class objects
can you create a method that has a parameter whose
type is a singleton?
yes, a parameter is a variable that stores a reference to an
object and there is one singleton object
4
undefined
Immutable classes
 
5
Immutable Classes
6
 
 
String
 is an example of an immutable class
a class defines an immutable type if an instance of the
class cannot be modified after it is created
each instance has its own constant state
other Java examples: 
Integer
 (and all of the other primitive
wrapper classes)
advantages of immutability versus mutability
easier to design, implement, and use
can never be put into an inconsistent state after creation
North American Phone Numbers
North American Numbering Plan is the standard used
in Canada and the USA for telephone numbers
telephone numbers look like
416-
736
-
2100
7
area
code
exchange
code
station
code
Designing a Simple Immutable Class
8
PhoneNumber
 API
none of these
features are static;
there are no
mutator methods
Recipe for Immutability
the recipe for immutability in Java is described by
Joshua Bloch in the book 
Effective Java
*
1.
Do not provide any methods that can alter the state
of the object
2.
Prevent the class from being extended
3.
Make all fields 
final
4.
Make all fields 
private
5.
Prevent clients from obtaining a reference to any
mutable fields
9
*highly recommended reading if you plan on becoming a Java programmer
revisit when we talk
about inheritance
revisit when we talk
about composition
undefined
10
public
 
final
 
class
 PhoneNumber {
  
private final
 
int
 
areaCode
;
  
private final
 
int
 
exchangeCode
;
  
private final
 
int
 
stationCode
;
  
public
 PhoneNumber(
int
 areaCode,
                     
int
 exchangeCode, 
int
 stationCode) {
    
this
.
areaCode
 = areaCode;
    
this
.
exchangeCode
 = exchangeCode;
    
this
.
stationCode
 = stationCode;
  }
undefined
11
  
public
 
int
 getAreaCode() {
    
return
 
this
.
areaCode
;
  }
  
public
 
int
 getExchangeCode() {
    
return
 
this
.
exchangeCode
;
  }
  
public
 
int
 getStationCode() {
    
return
 
this
.
stationCode
;
  }
undefined
12
  
@Override
  
public
 
boolean
 equals(Object obj) {
    
if
 (
this
 == obj) {
      
return
 
true
;
    }
    
if
 (obj == 
null
) {
      
return
 
false
;
    }
    
if
 (
this
.getClass() != obj.getClass()) {
      
return
 
false
;
    }
    PhoneNumber other = (PhoneNumber) obj;
    
if
 (
this
.
areaCode
 != other.
areaCode
 ||
        
this
.
exchangeCode
 != other.
exchangeCode
 ||
        
this
.
stationCode
 != other.
stationCode
) {
      
return
 
false
;
    }
    
return
 
true
;
  }
undefined
Mixing Static and Non-static
Multiton
13
Goals for Today
14
Multiton
review maps
static factory methods
Singleton UML Class Diagram
15
One Instance per State
16
 
the Java language specification guarantees that
identical 
String
 literals are not duplicated
 
 
 
 
 
prints: 
same object? true
the compiler ensures that identical 
String
 literals all
refer to the same object
a single instance per unique state
// client code somewhere
String s1 = "xyz";
String s2 = "xyz";
// how many String instances are there?
System.out.println("same object? " + (s1 == s2) );
[notes 4.5]
Multiton
17
 
a 
singleton
 class manages a single instance of the class
a 
multiton
 class manages multiple instances of the
class
 
what do you need to manage multiple instances?
a collection of some sort
 
how does the client request an instance with a
particular state?
it needs to pass the desired state as arguments to a method
Singleton vs Multiton UML Diagram
18
Singleton vs Multiton
19
 
Singleton
one instance
private static final Santa INSTANCE = new Santa();
 
zero-parameter accessor
public static Santa getInstance()
Singleton vs Multiton
20
 
Multiton
multiple instances (each with unique state)
 
private static final Map<String, PhoneNumber>
  instances = new TreeMap<String, PhoneNumber>();
 
accessor needs to provide state information
 
public static PhoneNumber getInstance(int areaCode,
                                    int exchangeCode,
                                    int stationCode)
Map
21
a map stores key-value pairs
Map<
String
, 
PhoneNumber
>
values are put into the map using the key
key type
value type
// client code somewhere
Map<String, PhoneNumber> m =
                      new TreeMap<String, PhoneNumber>;
PhoneNumber ago = new PhoneNumber(416, 979, 6648);
String key = "4169796648"
m.put(
key
, 
ago
);
[AJ 16.2]
Mutable Keys
22
from
http://docs.oracle.com/javase/7/docs/api/java/util/Map.html
Note: great care must be exercised if mutable objects are
used as map keys. The behavior of a map is not specified if
the value of an object is changed in a manner that affects
equals comparisons while the object is a key in the map.
undefined
23
 
public class MutableKey
{
  public static void main(String[] args)
  {
    Map<Date, String> m = new TreeMap<Date, String>();
    Date d1 = new Date(100, 0, 1);
    Date d2 = new Date(100, 0, 2);
    Date d3 = new Date(100, 0, 3);
    m.put(d1, "Jan 1, 2000");
    m.put(d2, "Jan 2, 2000");
    m.put(d3, "Jan 3, 2000");
    d2.setYear(101);           // mutator
    System.out.println("d1 " + m.get(d1));  // d1 Jan 1, 2000
    System.out.println("d2 " + m.get(d2));  // d2 Jan 2, 2000
    System.out.println("d3 " + m.get(d3));  // d3 null
  }
}
 
change TreeMap to HashMap and see what happens
don't mutate keys;
bad things will happen
Making 
PhoneNumber
 a Multiton
24
 
1.
multiple instances (each with unique state)
 
private static final Map<String, PhoneNumber>
  instances = new TreeMap<String, PhoneNumber>();
 
2.
accessor needs to provide state information
public static PhoneNumber getInstance(int areaCode,
                                     int exchangeCode,
                                     int stationCode)
getInstance()
 will get an instance from 
instances
 if the
instance is in the map; otherwise, it will create the new
instance and put it in the map
Making 
PhoneNumber
 a Multiton
25
 
3.
require private constructors
to prevent clients from creating instances on their own
clients should use 
getInstance()
 
4.
require immutability of 
PhoneNumber
s
to prevent clients from modifying state, thus making the
keys inconsistent with the 
PhoneNumber
s stored in the map
recall the recipe for immutability...
undefined
26
public class PhoneNumber
{
  
private static final Map<String, PhoneNumber> instances =
                         new TreeMap<String, PhoneNumber>();
  private final short areaCode;
  private final short exchangeCode;
  private final short stationCode;
  
private
 PhoneNumber(int areaCode,
                      int exchangeCode,
                      int stationCode)
  { // validate and set the
  // areaCode, exchangeCode, and stationCode
  }
undefined
27
  public static PhoneNumber getInstance(int areaCode,
                                        int exchangeCode,
                                        int stationCode)
  {
    String key = "" + areaCode + exchangeCode + stationCode;
    PhoneNumber n = PhoneNumber.instances.get(key);
    if (n == null)
    {
      n = new PhoneNumber(areaCode, exchangeCode, stationCode);
      PhoneNumber.instances.put(key, n);
    }
    return n;
  }
  
// remainder of PhoneNumber class ...
why is validation not needed?
undefined
28
public class PhoneNumberClient {
  public static void main(String[] args)
  {
    PhoneNumber x = PhoneNumber.getInstance(416, 736, 2100);
    PhoneNumber y = PhoneNumber.getInstance(416, 736, 2100);
    PhoneNumber z = PhoneNumber.getInstance(905, 867, 5309);
    System.out.println("x equals y: " + x.equals(y) +
                      " and x == y: " + (x == y));
    System.out.println("x equals z: " + x.equals(z) +
                      " and x == z: " + (x == z));
  }
}
 
x equals y: true and x == y: true
x equals z: false and x == z: false
A Singleton Puzzle: What is Printed?
29
public class Elvis {
  public static final Elvis INSTANCE = new Elvis();
  private final int beltSize;
  private static final int CURRENT_YEAR =
    Calendar.getInstance().get(Calendar.YEAR);
  private Elvis() { this.beltSize = CURRENT_YEAR – 1930; }
  public int getBeltSize() { return this.beltSize; }
  public static void main(String[] args) {
    System.out.println("Elvis has a belt size of " +
                        INSTANCE.getBeltSize());
  }
}
from Java Puzzlers by Joshua Bloch and Neal Gafter
Slide Note
Embed
Share

- Singleton and utility classes in Java have distinct differences despite superficial similarities. Singleton represents an object, while utility is a class. Singleton can implement interfaces freely, allow static methods in Java 8 interfaces, and convert to non-singleton. In contrast, utility classes cannot create objects, accept a class as a parameter, or be used to create multiple instances. Immutable classes, like String, ensure instances cannot be modified post-creation, leading to easier design and consistent state.

  • - Java Design Patterns
  • Singleton
  • Utility Class
  • Immutable Classes
  • Object-oriented Programming

Uploaded on Nov 28, 2024 | 2 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.

E N D

Presentation Transcript


  1. Singleton vs utility class at first glance, the singleton pattern does not seem to offer any advantages to using a utility class i.e., a utility class with non-final static fields looks a lot like a single object with non-static fields there is a fundamental difference between a singleton and a utility class: a singleton represents an object whereas a utility is a class 1

  2. Singleton vs utility class suppose that you want your singleton/utility class to implement an interface up to and including Java 7, a utility class could not implement an interface a singleton can freely implement interfaces Java 8 now allows static methods in interfaces a utility class can now implement an interface that has all static methods but a utility class still cannot implement an interface having non- static methods (such as Iterable) 2

  3. Singleton vs utility class suppose that you decide later on that you need multiple instances rather than a singleton/utility class a utility class cannot be used to create objects of the utility class type a singleton can be converted to a non-singleton 3

  4. Singleton vs utility class can you create a method that has a parameter whose type is a utility class? no, a parameter is a variable that stores a reference to an object and there are no utility class objects can you create a method that has a parameter whose type is a singleton? yes, a parameter is a variable that stores a reference to an object and there is one singleton object 4

  5. Immutable classes 5

  6. Immutable Classes String is an example of an immutable class a class defines an immutable type if an instance of the class cannot be modified after it is created each instance has its own constant state other Java examples: Integer (and all of the other primitive wrapper classes) advantages of immutability versus mutability easier to design, implement, and use can never be put into an inconsistent state after creation 6

  7. North American Phone Numbers North American Numbering Plan is the standard used in Canada and the USA for telephone numbers telephone numbers look like 416-736-2100 area code exchange code station code 7

  8. Designing a Simple Immutable Class PhoneNumber API PhoneNumber - areaCode : int - exchangeCode : int - stationCode : int + PhoneNumber(int, int, int) + equals(Object) : boolean + getAreaCode() : int + getExchangeCode() : int + getStationCode() : int + hashCode() : int + toString() : String none of these features are static; there are no mutator methods 8

  9. Recipe for Immutability the recipe for immutability in Java is described by Joshua Bloch in the book Effective Java* Do not provide any methods that can alter the state of the object Prevent the class from being extended Make all fields final Make all fields private Prevent clients from obtaining a reference to any mutable fields 1. revisit when we talk about inheritance 2. 3. 4. 5. revisit when we talk about composition 9 *highly recommended reading if you plan on becoming a Java programmer

  10. public final class PhoneNumber { private final int areaCode; private final int exchangeCode; private final int stationCode; public PhoneNumber(int areaCode, int exchangeCode, int stationCode) { this.areaCode = areaCode; this.exchangeCode = exchangeCode; this.stationCode = stationCode; } 10

  11. public int getAreaCode() { return this.areaCode; } public int getExchangeCode() { return this.exchangeCode; } public int getStationCode() { return this.stationCode; } 11

  12. @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (this.getClass() != obj.getClass()) { return false; } PhoneNumber other = (PhoneNumber) obj; if (this.areaCode != other.areaCode || this.exchangeCode != other.exchangeCode || this.stationCode != other.stationCode) { return false; } return true; } 12

  13. Mixing Static and Non-static Multiton 13

  14. Goals for Today Multiton review maps static factory methods 14

  15. Singleton UML Class Diagram Singleton - INSTANCE : Singleton ... - Singleton() + getInstance() : Singleton ... 15

  16. One Instance per State the Java language specification guarantees that identical String literals are not duplicated // client code somewhere String s1 = "xyz"; String s2 = "xyz"; // how many String instances are there? System.out.println("same object? " + (s1 == s2) ); prints: same object? true the compiler ensures that identical String literals all refer to the same object a single instance per unique state [notes 4.5] 16

  17. Multiton a singleton class manages a single instance of the class a multiton class manages multiple instances of the class what do you need to manage multiple instances? a collection of some sort how does the client request an instance with a particular state? it needs to pass the desired state as arguments to a method 17

  18. Singleton vs Multiton UML Diagram Singleton - INSTANCE : Singleton ... - Singleton() + getInstance() : Singleton ... Multiton - instances : Map ... - Multiton() + getInstance(Object) : Multiton ... 18

  19. Singleton vs Multiton Singleton one instance private static final Santa INSTANCE = new Santa(); zero-parameter accessor public static Santa getInstance() 19

  20. Singleton vs Multiton Multiton multiple instances (each with unique state) private static final Map<String, PhoneNumber> instances = new TreeMap<String, PhoneNumber>(); accessor needs to provide state information public static PhoneNumber getInstance(int areaCode, int exchangeCode, int stationCode) 20

  21. Map a map stores key-value pairs Map<String, PhoneNumber> key type value type values are put into the map using the key // client code somewhere Map<String, PhoneNumber> m = new TreeMap<String, PhoneNumber>; PhoneNumber ago = new PhoneNumber(416, 979, 6648); String key = "4169796648" m.put(key, ago); [AJ 16.2] 21

  22. Mutable Keys from http://docs.oracle.com/javase/7/docs/api/java/util/Map.html Note: great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map. 22

  23. public class MutableKey { public static void main(String[] args) { Map<Date, String> m = new TreeMap<Date, String>(); Date d1 = new Date(100, 0, 1); Date d2 = new Date(100, 0, 2); Date d3 = new Date(100, 0, 3); m.put(d1, "Jan 1, 2000"); m.put(d2, "Jan 2, 2000"); m.put(d3, "Jan 3, 2000"); d2.setYear(101); // mutator System.out.println("d1 " + m.get(d1)); // d1 Jan 1, 2000 System.out.println("d2 " + m.get(d2)); // d2 Jan 2, 2000 System.out.println("d3 " + m.get(d3)); // d3 null } } change TreeMap to HashMap and see what happens don't mutate keys; bad things will happen 23

  24. Making PhoneNumber a Multiton multiple instances (each with unique state) 1. private static final Map<String, PhoneNumber> instances = new TreeMap<String, PhoneNumber>(); accessor needs to provide state information 2. public static PhoneNumber getInstance(int areaCode, int exchangeCode, int stationCode) getInstance() will get an instance from instances if the instance is in the map; otherwise, it will create the new instance and put it in the map 24

  25. Making PhoneNumber a Multiton require private constructors 3. to prevent clients from creating instances on their own clients should use getInstance() require immutability of PhoneNumbers 4. to prevent clients from modifying state, thus making the keys inconsistent with the PhoneNumbers stored in the map recall the recipe for immutability... 25

  26. public class PhoneNumber { private static final Map<String, PhoneNumber> instances = new TreeMap<String, PhoneNumber>(); private final short areaCode; private final short exchangeCode; private final short stationCode; private PhoneNumber(int areaCode, int exchangeCode, int stationCode) { // validate and set the // areaCode, exchangeCode, and stationCode } 26

  27. public static PhoneNumber getInstance(int areaCode, int exchangeCode, int stationCode) { String key = "" + areaCode + exchangeCode + stationCode; PhoneNumber n = PhoneNumber.instances.get(key); if (n == null) { n = new PhoneNumber(areaCode, exchangeCode, stationCode); PhoneNumber.instances.put(key, n); } return n; } // remainder of PhoneNumber class ... why is validation not needed? 27

  28. public class PhoneNumberClient { public static void main(String[] args) { PhoneNumber x = PhoneNumber.getInstance(416, 736, 2100); PhoneNumber y = PhoneNumber.getInstance(416, 736, 2100); PhoneNumber z = PhoneNumber.getInstance(905, 867, 5309); System.out.println("x equals y: " + x.equals(y) + " and x == y: " + (x == y)); System.out.println("x equals z: " + x.equals(z) + " and x == z: " + (x == z)); } } x equals y: true and x == y: true x equals z: false and x == z: false 28

  29. A Singleton Puzzle: What is Printed? public class Elvis { public static final Elvis INSTANCE = new Elvis(); private final int beltSize; private static final int CURRENT_YEAR = Calendar.getInstance().get(Calendar.YEAR); private Elvis() { this.beltSize = CURRENT_YEAR 1930; } public int getBeltSize() { return this.beltSize; } public static void main(String[] args) { System.out.println("Elvis has a belt size of " + INSTANCE.getBeltSize()); } } from Java Puzzlers by Joshua Bloch and Neal Gafter 29

More Related Content

giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#