65
Chapter 8 Singleton Summary prepared by Kirk Scott 1

Chapter 8 Singleton

  • Upload
    iman

  • View
    78

  • Download
    0

Embed Size (px)

DESCRIPTION

Chapter 8 Singleton. Summary prepared by Kirk Scott. Design Patterns in Java Chapter 8 Singleton. Summary prepared by Kirk Scott. Pileated Woodpecker From Wikipedia, the free encyclopedia - PowerPoint PPT Presentation

Citation preview

Page 1: Chapter  8 Singleton

1

Chapter 8Singleton

Summary prepared by Kirk Scott

Page 2: Chapter  8 Singleton

2

Design Patterns in JavaChapter 8Singleton

Summary prepared by Kirk Scott

Page 3: Chapter  8 Singleton

3

• Pileated Woodpecker• From Wikipedia, the free encyclopedia• The Pileated Woodpecker (Dryocopus pileatus) is a

very large North American woodpecker, roughly crow-sized, inhabiting deciduous forests in eastern North America, the Great Lakes, the boreal forests of Canada, and parts of the Pacific coast. It is also the largest woodpecker in the United States, excepting the possibly extinct Ivory-billed Woodpecker.

Page 4: Chapter  8 Singleton

4

• The name Dryocopus come from the Greek drus, an oak tree and kopos, a cutter.

Page 5: Chapter  8 Singleton

5

Page 6: Chapter  8 Singleton

6

Page 7: Chapter  8 Singleton

7

Page 8: Chapter  8 Singleton

8

Page 9: Chapter  8 Singleton

9

General Background on Responsibility

• On the whole:• Classes/objects should be responsible for

themselves• They should be self-sufficient• Their code should be internally consistent• They should not depend on other classes/objects• That is, they should not implement their

functionality by referring to other classes/objects

Page 10: Chapter  8 Singleton

10

Responsibility and Singleton

• In modeling a real problem domain, it can happen that for a given class there will be only one instance

• This situation is known as a singleton• The idea is that the code for the class itself should

control how many instances of it there are• It should not be the responsibility of all external

code to determine how many instances there are

Page 11: Chapter  8 Singleton

11

• If there is a singleton class, responsibility for maintaining it as a singleton can be centralized in the class itself

• In the context of the whole application, responsibility for this part of the design has been centralized

Page 12: Chapter  8 Singleton

12

• Viewed from another perspective of client code:

• Client code is relieved of a responsibility which doesn’t really belong to it

• However, this does mean that client code becomes dependent on the correct implementation of the singleton logic in the singleton class

Page 13: Chapter  8 Singleton

13

• This is not surprising• One piece of code is always, ultimately

dependent on the correct implementation of other pieces of code

• The situation simply is that if a singleton can be identified, and enforcement is desirable, then enforcement should preferably be done in the class that there should only be one instance of

Page 14: Chapter  8 Singleton

14

Book Definition of the Pattern

• Book definition:• The intent of the Singleton pattern is to ensure

that a class has only one instance and to provide a global point of access to it.

Page 15: Chapter  8 Singleton

15

• The authors state, “The mechanics of Singleton are more memorable than its intent.”

• You might translate this to say that the pattern can be motivated or explained in terms of responsibility

• But its fundamental action and structure has to do with construction and how best to implement it in a given situation.

Page 16: Chapter  8 Singleton

16

Implementing the Pattern

• Challenge 8.1• How can you prevent other developers from

constructing new instances of your class?

Page 17: Chapter  8 Singleton

17

• Solution 8.1• “To prevent other developers from

instantiating your class, create a single constructor with private access.

• Note that if you create other, nonprivate constructors or no constructors at all, other objects will be able to instantiate your class”

Page 18: Chapter  8 Singleton

18

• Comment mode on:• First, remember this factoid from 202:• If you provide no constructors at all, the

system will provide a default constructor• That’s how come no constructors at all will

allow others to create instances• Obviously, making public constructors will also

allow others to make instances

Page 19: Chapter  8 Singleton

19

• The idea of a private constructor has not come up before

• If you have a private constructor, the question becomes, how and where do you call it from?

• The Factory class definition on the following overhead illustrates the solution that the authors are proposing

Page 20: Chapter  8 Singleton

20

• public class Factory• {• private static Factory factory = new Factory();• private Factory()• {• }• public static getFactory()• {• return factory;• }• }

Page 21: Chapter  8 Singleton

21

• The class contains a private, static instance of itself

• Inline construction of the instance is done, one time, by a call to the default constructor

• The default constructor is private, so it can’t be called by outside code

Page 22: Chapter  8 Singleton

22

• The static getFactory() method returns a reference to the singleton, the static instance of the class

• The call to the get method in a client piece of code would be like any call to a static method:

• Factory singletonReference = Factory.getFactory();

Page 23: Chapter  8 Singleton

23

Thinking of an Alternative Approach to Implementing the Pattern

• The book’s solution works• Not having considered the possibility of

private constructors or classes containing instance variables which are instances of themselves, this is not the first solution approach that would have occurred to me

• I would have been thinking along different lines

Page 24: Chapter  8 Singleton

24

A Non-Solution

• The following overhead shows a starting approach to solving the problem

• Notice that it is incomplete, i.e., wrong• The reason for pursuing it is as a reminder of

what things are and what they do in Java• This helps put the book’s solution into

perspective

Page 25: Chapter  8 Singleton

25

• /* An approach to creating a singleton that doesn’t work. */

• public class Factory• {• private static int instanceCount = 0;• public Factory()• {• if(instanceCount == 0)• // do the construction• else• // don’t do the construction• }• }

Page 26: Chapter  8 Singleton

26

• What is wrong with this?• You are stopped when you realize that a

constructor is a constructor• It is supposed to return a reference to a newly

created object• What does the constructor “return” if nothing

is to be constructed?

Page 27: Chapter  8 Singleton

27

• Syntactically, could a constructor return a null reference rather than a reference to an object?

• It doesn’t matter what the answer to that question is.

• Even if it could, that would not be desirable.• Users expect constructors to return references

to actual objects of the type desired

Page 28: Chapter  8 Singleton

28

A Halfway Solution Reviewing Exception Throwing

• On the other hand, a constructor, like a method, can be declared to throw an exception

• Then the code can be written either to run successfully and return a reference to a newly created object

• Or to throw an exception if the conditions for the Singleton design pattern aren’t met

Page 29: Chapter  8 Singleton

29

• public class Factory• {• private static int instanceCount = 0;• public Factory() throws Exception• {• if(instanceCount == 0)• instanceCount++;• else• throw new Exception(“Uh-oh”);• }• }

Page 30: Chapter  8 Singleton

30

• Although the previous code isn’t the way the book does it, the code compiles

• The thing client code would have to keep in mind is that a call to the constructor would have to be done in a try/catch block

• This solution does restrict a class to having at most one instance

Page 31: Chapter  8 Singleton

31

Why is this only a Halfway Solution?

• With this solution, one client can call the constructor one time and obtain a reference to the singleton

• “Singleton-ness” is supported• However, the pattern definition said an

implementation has to provide a global point of access to the one instance

Page 32: Chapter  8 Singleton

32

• The halfway solution does not provide a mechanism whereby multiple clients at different times could obtain a reference to the singleton that is created

• The exception throwing is an ugly way of letting client code know a singleton already exists

• Once the singleton has been created, the burden is on the client code to maintain a reference to it and make it available

Page 33: Chapter  8 Singleton

33

• The flaw of this solution can be explained in terms of responsibility

• Under the halfway solution, responsibility for making the one instance of the singleton is centralized in the singleton class (good).

• However, responsibility for knowing and keeping track of the singleton is decentralized into the client code (bad).

• In other words, it’s not just a halfway solution syntactically

• It’s a halfway solution in terms of responsibility

Page 34: Chapter  8 Singleton

34

• The conclusion is this:• It is desirable to centralize all aspects of a singleton in

the singleton class• Trying to deal with them on a piecemeal basis in every

piece of potential client code is not good• There could be many places where this would have to

be done• This is both inefficient and prone to error, either by

writing in correct code or by missing a place where the code should be included

Page 35: Chapter  8 Singleton

35

Lazy Initialization

• Next, the book introduces what it calls lazy initialization

• The idea is that an instance of the Singleton class is only constructed if some piece of client code requests a reference to it

• This requires removing the construction from the line declaring the instance variable

• Construction is then inserted into the getFactory() method

• This is shown on the next overhead

Page 36: Chapter  8 Singleton

36

• public class Factory• {• private static Factory factory;• private Factory()• {• }• public static Factory getFactory()• {• if(factory == null)• factory = new Factory();• return factory;• }• }

Page 37: Chapter  8 Singleton

37

• Notice how the logic of this approach does echo the halfway approach somewhat

• Construction is conditional• Depending on your preference, this solution may

also be nicer than the first book solution because you are calling the constructor from within a method

• There is nothing wrong with inline initialization, but some people may not prefer it

Page 38: Chapter  8 Singleton

38

• Challenge 8.2• Why might you decide to lazy-initialize a

singleton instance rather than to initialize it in its field declaration?

Page 39: Chapter  8 Singleton

39

• Solution 8.2• “Two reasons for lazy-initializing singletons are as

follows.• 1. You might not have enough information to

instantiate a singleton at static initialization time.

• For example, a Factory singleton might have to wait for the real factory’s machines to establish communication channels.

Page 40: Chapter  8 Singleton

40

• 2. You might choose to lazy-initialize a singleton that requires resources, such as a database connection, especially if there is a chance that the containing application will not need the singleton in a particular session.”

Page 41: Chapter  8 Singleton

41

• Whether you lazy initialize or not, construction of the singleton takes place in the singleton’s class

• And access to the singleton is provided through a public, static method

Page 42: Chapter  8 Singleton

42

Singletons and Threads

• CSCE 320 is not a pre-requisite for CSCE 302• This subsection in the book depends on

understanding concepts from CSCE 320, so it is not part of CSCE 302

• If you have had CSCE 320, the idea can be summarized pretty easily

• If you are trying to maintain a singleton, then you have to synchronize calls to the method which constructs the singleton

Page 43: Chapter  8 Singleton

43

• Without synchronization, it would be possible for two different threads to each create an instance of a so-called singleton

• If you do synchronize correctly on construction, and there is one object, you also need to keep in mind that by definition, the goal was apparently to have a shared object, which means you also need to synchronize method calls on the object so it doesn’t enter an inconsistent state

Page 44: Chapter  8 Singleton

44

Recognizing Singleton

• In most applications you can generally have multiple instances of a given class

• It may be the case that for a particular application, under certain conditions, only one instance of a given class is needed

• Even in this case, the client code may be simple enough that there is simply one place where that instance is created, and there is no need to include the singleton machinery in the class

Page 45: Chapter  8 Singleton

45

• In reality, singletons are rare• The trick is learn how to identify that situation• For what it’s worth, I had a student once who said he

had applied that pattern in an application• He was writing code in a networked environment

where logging of events was handled by a singleton logger class

• It was desirable for multiple, different pieces of networked client code to have a common log, not separate logs for each client (process)

Page 46: Chapter  8 Singleton

46

Some More Observations on the Pattern

• The authors say that Singleton is probably the best known pattern

• This may be because it is easy to understand• It may also be because, for C style

programmers, it makes it easy to get around the requirements of object-oriented programming

• A singleton object can serve as a global type of variable

Page 47: Chapter  8 Singleton

47

• In general, the reason for the existence of a singleton is some restriction in the problem domain

• A singleton shouldn’t be introduced unless a good reason can be found for having one

• Client code, if at all possible, should have no interest in special conditions on the creation of instances of other classes (like singletons)

Page 48: Chapter  8 Singleton

48

Singleton and Subclasses

• Note that if a class is to have subclasses, the singleton pattern won’t work

• Recall that construction in a subclass depends on the existence of a suitable constructor in the superclass

• The first thing in a subclass constructor is a call to super (not shown if you are relying on a default constructor in the superclass

Page 49: Chapter  8 Singleton

49

• If the call to super (the superclass constructor) fails to accomplish construction of a new object because it’s a singleton class and the singleton was already created, then the subclass constructor is doomed to fail

• The best you could hope for is to call the subclass constructor one time, at which point the superclass singleton is created, and from there on you can’t construct anymore instances of either class

Page 50: Chapter  8 Singleton

50

• On the one hand, there is a logic to this:• If the superclass was a singleton, the subclass is

also a singleton• The sticky point is that if you want an instance of

the subclass, that has to be done first• If you make an instance of the superclass first,

from that point on, you can’t make an instance of the subclass

• Basically, this is a mess you don’t want to deal with

Page 51: Chapter  8 Singleton

51

Another Example

• It will be clear that the following example is not taken from some real business application.

• It is given simply as a way of reiterating the idea of a singleton and how to accomplish it in code.

• This is an old test question, brought back to life for teaching purposes

Page 52: Chapter  8 Singleton

52

• The code on the following overhead shows• A private static instance variable• A private default constructor• A method that does lazy initialization of the

instance variable• This is the full pattern as given in the book

Page 53: Chapter  8 Singleton

53

• public class MonotheisticGod• {• private static MonotheisticGod oneGod;• private String explanation;

• private MonotheisticGod()• {• explanation = “There is only one of me.”;• }

• public static MonotheisticGod getMonotheisticGod()• {• if(oneGod == null)• oneGod = new MonotheisticGod();

• return oneGod;• }• }

Page 54: Chapter  8 Singleton

54

• The code on the following overhead shows a call to obtain a reference to the foregoing singleton.

Page 55: Chapter  8 Singleton

55

• public class TestGod• {• public static void main(String[] args)

• {• MonotheisticGod myOneGod = MonotheisticGod.getMonotheisticGod();

• System.out.println(myOneGod);• }• }

Page 56: Chapter  8 Singleton

56

• This is would be the output of the program:

• MonotheisticGod[explanation=“There is only one of me.”]

Page 57: Chapter  8 Singleton

57

UML for the Pattern

• The singleton pattern is quite simple structurally

• There is no one accepted UML diagram that illustrates it

• You might include it or recognize it in a UML diagram by a detailed listing of the instance variables and methods of the class

Page 58: Chapter  8 Singleton

58

• You might also include it or recognize it by means of a diagram showing that a class has a reference to an instance of itself—specifically with a cardinality value of 1 at the end of the arrowhead

• This second option is illustrated on the following overhead

Page 59: Chapter  8 Singleton

59

Page 60: Chapter  8 Singleton

60

Lasater’s UML Diagram

• Lasater’s UML diagram is given on the next overhead.

• Using that author’s terminology, the pattern is recognizable by the instance variable, constructor, and instance() method given in the full class diagram.

Page 61: Chapter  8 Singleton

61

Page 62: Chapter  8 Singleton

62

Summary

• The Singleton pattern means only one object of a given class will be created

• By definition, this means there is a single, global occurrence of the class

• Lazy initialization can be a useful feature of the implementation of Singleton

• In a multi-threaded environment synchronization has to be used in order to make sure that an implementation of singleton works correctly

Page 63: Chapter  8 Singleton

63

• Keep in mind that just because there is only one instance of a class in a given application, that doesn’t mean that the singleton pattern is appropriate

• From a pragmatic point of view, this warning is especially apropos if the class has subclasses

• Singleton doesn’t really work for a class with subclasses

Page 64: Chapter  8 Singleton

64

• The Singleton pattern centralizes responsibility in a single instance of a class by hiding the constructor and providing a single point of access to object creation

Page 65: Chapter  8 Singleton

65

The End