Download - Stoop 432-singleton

Transcript
Page 1: Stoop 432-singleton

Stéphane Ducasse 1

Stéphane [email protected]://stephane.ducasse.free.fr/

Singleton

Page 2: Stoop 432-singleton

S.Ducasse 2

Singleton’s Intent

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

Page 3: Stoop 432-singleton

S.Ducasse 3

Problem / Solution

Problem: We want a class with a unique instance.

Solution: Store the first time an instance is created and return it each time a new instance is requested.

Page 4: Stoop 432-singleton

S.Ducasse 4

Example

db := DBConnect default.db2 := DBConnect default.

db2 == db2> true

Yes we get only one instance

Page 5: Stoop 432-singleton

S.Ducasse 5

Example

Object subclass: #DBConnectinstanceVariableNames: ''classVariableNames: 'UniqueInstance'poolDictionaries: ''category: 'MyDB'

Page 6: Stoop 432-singleton

S.Ducasse 6

Implementation

NetworkManager class>>new self error: ‘should use uniqueInstance’

NetworkManager class>>uniqueInstanceUniqueInstance isNil ifTrue: [ UniqueInstance := self basicNew initialize].^UniqueInstance

Page 7: Stoop 432-singleton

S.Ducasse 7

Implementation Issues

Singletons may be accessed via a global variable

Pharo 1.1Smalltalk points to SmalltalkImage current

Global access is good to get shorter expressionSmalltalk vs SmalltalkImage current

But this should be more the exception than the rule

Page 8: Stoop 432-singleton

S.Ducasse 8

Global Variable or Class Method Access

Global Variable Access is dangerous: if we reassign Smalltalk we lose all references to the current SmalltalkImage

Class Method Access is better because it provides a single access point. This class is responsible for the singleton instance (creation, initialization,...).

Page 9: Stoop 432-singleton

S.Ducasse 9

Implementation Issues

Persistent Singleton: only one instance exists and its identity does not change

Transient Singleton: only one instance exists at any time, but that instance changes

Single Active Instance Singleton: a single instance is active at any point in time, but other dormant instances may also exist.

Page 10: Stoop 432-singleton

S.Ducasse 10

classVariable or class instance variable

classVariable (shared variable)One singleton for a complete hierarchy

Class instance variableOne singleton per class

Page 11: Stoop 432-singleton

S.Ducasse 11

Access?

In Smalltalk we cannot prevent a client to send a message (protected in C++). To prevent additional creation we can redefine new/new:

DBConnect class>>newself error: ‘Class ‘, self name, ‘ cannot create new instances’

11

Page 12: Stoop 432-singleton

S.Ducasse 12

Access using new: not good idea

DBConnect class>>new^self uniqueInstance

The intent (uniqueness) is not clear anymore!

new is normally used to return newly created instances.

Not intention revealing

Page 13: Stoop 432-singleton

S.Ducasse 13

new vs uniqueInstance

The difference between #new and #uniqueInstance is that #new potentially initializes a new instance, while #uniqueInstance only returns the unique instance (there is no initialization)

Do we want to communicate that the class has a singleton? new? defaultInstance? uniqueInstance?

Page 14: Stoop 432-singleton

S.Ducasse 14

Favor Instance Behavior

When a class should only have one instance, it is tempting to define all its behavior at the class level.

This is not optimal:Class behavior represents behavior of classes: “Ordinary objects are used to model the real world. MetaObjects describe these ordinary objects”Now yes this may be tedious to type DBConnect current reconnect instead of DBConnect reconnect

What’s happens if later on an object can have multiple instances? You have to change a lot of client code!

Page 15: Stoop 432-singleton

S.Ducasse 15

Time and not Scope

Singleton is about time not accesstime: only one instance is available at the same timeaccess: can’t you add an instance to refer to the object?

Singleton for access are as bad as global variables

Often we can avoid singleton by passing/referring to the object instead of favoring a global access point

It is worth to have one extra instance variable that refers to the right object


Top Related