Upload
yael-perry
View
43
Download
0
Embed Size (px)
DESCRIPTION
Unit 3 Singleton. Summary prepared by Kirk Scott. Design Patterns in Java Chapter 8 Singleton. Summary prepared by Kirk Scott. General Background on Responsibility and the Singleton Design Pattern. Objects in general should be responsible for themselves - PowerPoint PPT Presentation
Citation preview
1
Unit 3Singleton
Summary prepared by Kirk Scott
2
Design Patterns in JavaChapter 8Singleton
Summary prepared by Kirk Scott
3
General Background on Responsibility and the Singleton Design Pattern
• Objects in general should be responsible for themselves
• That means that they should be internally consistent
• It also means that they are self-sufficient• They do not depend (on the whole) on other
classes/objects• They do not implement their functionality by
referring to other classes/objects
4
• 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 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
5
• 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
• Viewed from another perspective, client code is relieved of the responsibility, but in a sense it then becomes dependent on the logic implemented in the singleton class
6
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.
7
• The authors state, “The mechanics of Singleton are more memorable than its intent.”
• You might say that the pattern incidentally involves the apportionment of responsibility, but its purpose really has to do with construction rather than responsibility itself.
8
Implementing the Pattern
• Challenge 8.1• How can you prevent other developers from
constructing new instances of your class?
9
• 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
10
• Comment mode on:• 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?
11
• The Factory class definition on the following overhead illustrates the solution that the authors are proposing
• The Factory class contains a default constructor which is declared private
• It also contains a static method which returns a reference to an instance of the class
• The class definition is followed by comments on how it works.
12
• public class Factory• {• private static Factory factory = new Factory();• private Factory()• {• }• public static getFactory()• {• return factory;• }• }
13
• The class contains a static instance of itself as an instance variable
• The variable is constructed (once) in its declaration by a call to the private constructor
• The class also contains a static getFactory() method which returns a reference to the singleton
• 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();
14
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
15
• The following overhead shows a starting approach to solving the problem
• Notice that it is incomplete• You are stopped when you realize that a
constructor is a constructor
16
• /* 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• }• }
17
• A constructor is different from a method• You don’t have the choice of conditionally either
returning a reference to an object or not• The constructor should return a reference to an
object• The object is actually created ultimately by the fact
that constructor calls are bucked up to the Object class
• All the local constructor code does is initialize instance variables.
18
• However, 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
19
• public class Factory• {• private static int instanceCount = 0;• public Factory() throws Exception• {• if(instanceCount == 0)• instanceCount++;• else• throw new Exception(“Uh-oh”);• }• }
20
• 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
21
• On the other hand, it’s not a good solution• This solution puts the burden on the client
code of keeping track of whether an instance has been created before
• This solution doesn’t support the idea that at various points in the client or in various clients you would call more than once, wanting to get a reference to the one instance of the class
22
• There is a paradox here:• If an instance has been created, then the
client code should “know” that—or keep track of it—and there would be no occasion to call the constructor again
23
• In other words, in terms of responsibility and centralization, this solution decentralizes responsibility.
• Responsibility for making sure there is only one instance is still centralized in the singleton class.
• But if there are >1 client and one creates the instance, then any other client that tries to create an instance will receive an exception.
• Clients have responsibility for noting whether or not the one instance has already been created.
24
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
25
• public class Factory• {• private static Factory factory;• private Factory()• {• }• public static getFactory()• {• if(factory == null)• factory = new Factory();• return factory;• }• }
26
• Challenge 8.2• Why might you decide to lazy-initialize a
singleton instance rather than to initialize it in its field declaration?
27
• 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.
28
• 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.
29
• 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
30
Singletons and Threads
• CS 320 is not a pre-requisite for CS 304• This subsection depends on understanding concepts from
CS 320, so it is not part of CS 304• If you have had CS 320, the idea can be summarize pretty
easily• If you are trying to maintain a singleton, then you have to
synchronize calls to the method which constructs the singleton
• Without synchronization, it would be possible for two different threads to each create an instance of a so-called singleton
31
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
• In reality, singletons are rare• The trick is learn how to identify that situation
32
• 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
33
• 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)
34
• Note that if a class is to have subclasses or different versions, singleton won’t work at all
• The restrictions on construction in the superclass will mess up construction in the subclasses
35
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.
• The code on the following overhead shows a class implemented using the singleton pattern using the coding technique suggested by the book.
36
• public class MonotheisticGod• {• private static MonotheisticGod oneGod;
• private MonotheisticGod()• {• }
• public static MonotheisticGod getMonotheisticGod()• {• if(oneGod == null)• oneGod = new MonotheisticGod();
• return oneGod;• }• }
37
• The code on the following overhead shows a call to obtain a reference to the foregoing singleton.
38
• public class TestGod• {• public static void main(String[] args)
• {• MonotheisticGod myOneGod = MonotheisticGod.getMonotheisticGod();
• System.out.println(myOneGod);• }• }
39
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
40
• You might also include it or recognize it by means of a cardinality value of 1 at the end of an arrow representing navigability and showing that the class has an instance of itself
• This second option is illustrated on the following overhead
41
42
• 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.
43
44
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
45
• 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
• 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
46
The End
47
• The following blocks of stuff are stored here for reference.
• They come up in the book, but they will not be presented in class.
48
Singletons and Threads
• CS 320 is not a pre-requisite for CS 304• This subsection depends on understanding
concepts from CS 320, so it is not part of CS 304
• If you have had CS 320, you should be able to read the section and get the idea
• It will be presented in brief here.
49
• Suppose that you do lazy initialization• The goal of the getFactory() method is to construct
only one instance• Suppose you have two client threads which can
call getFactory()• If you don’t synchronize on the call to getFactory(),
both threads could run the method concurrently, resulting in the construction of two Factory objects
• This defeats the goal of implementing a singleton
50
• The book proposes a solution that is based on using the lock concept in Java
• Alternative coding solutions are available since Java has lots of stuff in the API related to threads and synchronization
• The book presents sample code, a challenge, and solution code
51
• None of that will be pursued• If you haven’t had CS 320, you can ignore the
whole topic• It has only been addressed briefly here for the
benefit of those who have already taken CS 320
52
• The following overheads are stored here for reference purposes.
• This is stuff that came from the book, but which won’t be covered in class because it seems to be of limited utility.
• Consider the following UML diagram
53
54
• Challenge 8.4• For each class in Figure 8.1, say whether it
appears to be a singleton class, and why.• Spoiler mode on:• The authors aren’t really satisfied that any of
these classes they’ve given are a good example of a singleton…
55
• Solution 8.4• OurBiggestRocket: • This class has an inappropriate name. • You would normally model attributes, such as
“biggest,” with attributes, not with class names. • If a developer must sustain this class, perhaps it is a
singleton.• TopSalesAssociate: • This class has the same problem as OurBiggestRocket.
56
• Math: • This class is a utility, with all static methods and no instances.
• It is not a singleton. • Note that it does, however, have a private
constructor. • [Why? I don’t know.]• System: • This is also a utility.
57
• PrintStream: • Although the System.out object is a PrintStream object
with unique responsibilities, it is not a unique instance of PrintStream, which is not a singleton class.
• PrintSpooler: • PrintSpoolers are associated with one or a few printers; • it’s unlikely that this is a singleton.• PrinterManager: • At Oozinoz, you have many printers, and you can look up
their addresses through the PrinterManager singleton.