design patterns and refactoring - singletonhaase/lehre/thisterm/... · design patterns and...

23
Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 1 / 19

Upload: others

Post on 12-Aug-2020

17 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Design Patterns and RefactoringSingleton

Oliver Haase

HTWG Konstanz

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 1 / 19

Page 2: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Description I

Classification: object based creational pattern

Puropse:

ensure that a class can be instantiated exactly onceprovide global access point to single instance

Application Examples:

exactly one driver for a piece if hardware (e.g. printer)exactly one socket listener that receives incoming requestsapplication that can be started only onceglobal event queue for discrete event simulation

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 2 / 19

Page 3: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Description II

Structure:

Members:Singleton

responsible for creation of the instanceprovides static operation for access to the instance

Interactions: clients access singleton instance through getInstanceoperation

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 3 / 19

Page 4: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Description III

Alternative: Class with static variables and static methods

Drawbacks:

Java interfaces cannot contain static methods→ class cannot be hidden behind interface

each method invocation contains class name→ undermines polymorphism

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 4 / 19

Page 5: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Description III

Alternative: Class with static variables and static methods

Drawbacks:

Java interfaces cannot contain static methods→ class cannot be hidden behind interface

each method invocation contains class name→ undermines polymorphism

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 4 / 19

Page 6: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Implementation

Singleton implementation with Lazy Instantiation

1 p u b l i c c l a s s MySing le ton {2 p r i v a t e s t a t i c MySing le ton i n s t a n c e = n u l l ;3 p r i v a t e MySing le ton ( ) {4 . . .5 }6 p u b l i c s t a t i c MySing le ton g e t I n s t a n c e ( ) {7 i f ( i n s t a n c e == n u l l ) {8 i n s t a n c e = new MySing le ton ( ) ;9 }

10 r e t u r n i n s t a n c e ;11 }12 . . .13 }

Problem: Can lead to several instances if thread gets interrupted betweenlines 7 and 8→ not thread-safe!

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 5 / 19

Page 7: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Implementation

Singleton implementation with Lazy Instantiation

1 p u b l i c c l a s s MySing le ton {2 p r i v a t e s t a t i c MySing le ton i n s t a n c e = n u l l ;3 p r i v a t e MySing le ton ( ) {4 . . .5 }6 p u b l i c s t a t i c MySing le ton g e t I n s t a n c e ( ) {7 i f ( i n s t a n c e == n u l l ) {8 i n s t a n c e = new MySing le ton ( ) ;9 }

10 r e t u r n i n s t a n c e ;11 }12 . . .13 }

Problem: Can lead to several instances if thread gets interrupted betweenlines 7 and 8→ not thread-safe!

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 5 / 19

Page 8: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Implementation

Singleton implementation with Lazy Instantiation

1 p u b l i c c l a s s MySing le ton {2 p r i v a t e s t a t i c MySing le ton i n s t a n c e = n u l l ;3 p r i v a t e MySing le ton ( ) {4 . . .5 }6 p u b l i c s t a t i c MySing le ton g e t I n s t a n c e ( ) {7 i f ( i n s t a n c e == n u l l ) {8 i n s t a n c e = new MySing le ton ( ) ;9 }

10 r e t u r n i n s t a n c e ;11 }12 . . .13 }

Problem: Can lead to several instances if thread gets interrupted betweenlines 7 and 8→ not thread-safe!

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 5 / 19

Page 9: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Implementation

Resolve concurrency problem through synchronization:

p u b l i c c l a s s MySing le ton {p r i v a t e s t a t i c MySing le ton i n s t a n c e = n u l l ;p r i v a t e MySing le ton ( ) {

. . .}p u b l i c s t a t i c synchron ized MySing le ton g e t I n s t a n c e ( ){

i f ( i n s t a n c e == n u l l ) {i n s t a n c e = new MySing le ton ( ) ;

}r e t u r n i n s t a n c e ;

}. . .

}

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 6 / 19

Page 10: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Implementation

Problem: Only first call of getInstance needs to be synchronized:

→ unnecessary reduction of concurrency

→ synchronized Methods always slower than unsynchronized methods:

test program with 109 sequential getInstance calls on Mac Mini, 2GHz Intel Core 2 Duo, 1 GB RAM, 120 GB hard drive:

unsynchronized 4 sec.synchronized 58 sec.

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 7 / 19

Page 11: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Implementation

Implementation with Checked Locking

1 p u b l i c c l a s s MySing le ton {2 p r i v a t e s t a t i c MySing le ton i n s t a n c e = n u l l ;3 p r i v a t e MySing le ton ( ) {4 . . .5 }6 p u b l i c s t a t i c MySing le ton g e t I n s t a n c e ( ) {7 i f ( i n s t a n c e == n u l l ) {8 synchron ized ( MySing le ton . c l a s s ) {9 i n s t a n c e = new MySing le ton ( ) ;

10 }11 }12 r e t u r n i n s t a n c e ;13 }14 . . .15 }

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 8 / 19

Page 12: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Implementation

Scenario:

Thread1 gets interrupted between lines 8 and 9 → holds monitor ofMySingleton class object, no singleton instance created yet.

Thread2 passes 7, waits at 8 for Thread1

Thread1 finishes, creates singleton instance

Thread2 finishes, creates second ‘singleton’ instance

→ not thread-safe!

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 9 / 19

Page 13: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Implementation

Solution attempt using Double-Checked-Locking-(Anti-)Pattern:

1 p u b l i c c l a s s MySing le ton {2 p r i v a t e s t a t i c MySing le ton i n s t a n c e = n u l l ;3 p r i v a t e MySing le ton ( ) {4 . . .5 }6 p u b l i c s t a t i c MySing le ton g e t I n s t a n c e ( ) {7 i f ( i n s t a n c e == n u l l ) {8 synchron ized ( MySing le ton . c l a s s ) {9 i f ( i n s t a n c e == n u l l ) {

10 i n s t a n c e = new MySing le ton ( ) ;11 }12 }13 }14 r e t u r n i n s t a n c e ;15 }16 . . .17 }

Works well — or does it?Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 10 / 19

Page 14: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Implementation

Problem: Thread scheduling happens on the level of byte code, not on theJava source code level . . . object creation in line 10

i n s t a n c e = new MySing le ton ( ) ;

is mapped to the following pseudo byte code

1 ptrMemory = a l locateMemory ( )2 ass ignMemory ( i n s t an c e , ptrMemory )3 c a l lMyS i n g l e t o nCon s t r u c t o r ( i n s t a n c e )

If scheduling takes place between lines 2 and 3 then

instance != null, even though

instance has not been properly initialized

⇒ Thread2 might return uninitialized object instance, if thread 10 isinterrupted within line 10!

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 11 / 19

Page 15: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Implementation

The simple things are often the best — or: Life can be that simple!→ fully functional, performant solution:

p u b l i c c l a s s MySing le ton {p r i v a t e s t a t i c MySing le ton i n s t a n c e = new MySing le ton ( ) ;

p r i v a t e MySing le ton ( ) {. . .

}p u b l i c s t a t i c MySing le ton g e t I n s t a n c e ( ) {

r e t u r n i n s t a n c e ;}. . .

}

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 12 / 19

Page 16: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Implementation

Consequences of the simple implementation

Singleton instance is created (exactly once) at class loading time

even if it will never be used → but:

this rarely happens because class loading is usually triggered by usagerather small damage

Time consumption at loading rsther than at first usage → neitherbetter nor worse, only different . . .

potential drawback: class loading order hardly predictable→ Problem, if one singleton instance is needed to create another

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 13 / 19

Page 17: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Implementation

Consequences of the simple implementation

Singleton instance is created (exactly once) at class loading time

even if it will never be used → but:

this rarely happens because class loading is usually triggered by usagerather small damage

Time consumption at loading rsther than at first usage → neitherbetter nor worse, only different . . .

potential drawback: class loading order hardly predictable→ Problem, if one singleton instance is needed to create another

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 13 / 19

Page 18: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Usage

Joi 1 programming language supports singleton pattern:

s i n g l e t o n component MyComponent p r o v i d e s My In t e r f a c e {. . .

}

The current Joi implementation maps the Joi code to correspondingJava code.

Reason: Joi doesn’t support static class members→ static variables are modelled as members of a singleton class→ frequent usage of the singleton pattern

Java Webstart: Technology for the dynamic download, execution andupdating of applications

1more informationen at http://www-home.htwg-konstanz.de/˜haase/hp/joi.html andin [von Drachenfels, Haase, Walter. Joi - eine Java–Spracherweiterung zur Reduzierungvon Codeabhangigkeiten. In HTWG Forum, 2008/2009]

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 14 / 19

Page 19: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Singleton – Additional Considerations

Sometimes, a singleton object needs to be configured at creation time (orat the time of first usage)Example: Socket listener that needs to listen on certain portPossible Realizations:

add parameters to getInstance method:

p u b l i c c l a s s CS1 {p r i v a t e s t a t i c CS1 i n s t a n c e = new CS1 ( ) ;p r i v a t e i n t s t a t e ;p r i v a t e CS1 ( ) {}p r i v a t e v o i d c o n f i g ( i n t s t a t e ) {

t h i s . s t a t e = s t a t e ;}p u b l i c s t a t i c CS1 g e t I n s t a n c e ( i n t s t a t e ) {

i n s t a n c e . c o n f i g ( s t a t e ) ;r e t u r n i n s t a n c e ;

}}

→ params need to be passed into all subsequent getInstance calls

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 15 / 19

Page 20: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Singleton – Additional Considerations

two overloaded getInstance methods with and w/o parameters

p u b l i c c l a s s CS2 {p r i v a t e s t a t i c CS2 i n s t a n c e = new CS1 ( ) ;p r i v a t e i n t s t a t e ;p r i v a t e CS2 ( ) {}p r i v a t e vo id c o n f i g ( i n t s t a t e ) {

t h i s . s t a t e = s t a t e ;}p u b l i c s t a t i c CS2 g e t I n s t a n c e ( i n t s t a t e ) {

i n s t a n c e . c o n f i g ( s t a t e ) ;r e t u r n i n s t a n c e ;

}p u b l i c s t a t i c CS2 g e t I n s t a n c e ( ) {

r e t u r n i n s t a n c e ;}

}

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 16 / 19

Page 21: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Singleton – Additional Considerations

getInstance method without params + separate config method;catch repeated config invocations

p u b l i c c l a s s CS3 {p r i v a t e s t a t i c CS3 i n s t a n c e = new CS3 ( ) ;p r i v a t e i n t s t a t e ;p r i v a t e boolean c o n f i g u r e d = f a l s e ;p r i v a t e CS3 ( ) {}p u b l i c synchron ized vo id c o n f i g ( i n t s t a t e )

throws Excep t i on {i f ( c o n f i g u r e d )

throw new Excep t i on ( ” a l r e a d y c o n f i g u r e d ” ) ;t h i s . s t a t e = s t a t e ;t h i s . c o n f i g u r e d = t rue ;

}p u b l i c s t a t i c CS3 g e t I n s t a n c e ( ) {

r e t u r n i n s t a n c e ;}

}

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 17 / 19

Page 22: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Singleton – Additional Considerations

getInstance method without params + separate static configmethod, catch repeated and/or missing config invocations

p u b l i c c l a s s CS4 {p r i v a t e s t a t i c CS4 i n s t a n c e = new CS4 ( ) ;p r i v a t e i n t s t a t e ;p r i v a t e s t a t i c boolean c o n f i g u r e d = f a l s e ;

p r i v a t e CS4 ( ) {}

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 18 / 19

Page 23: Design Patterns and Refactoring - Singletonhaase/lehre/thisterm/... · Design Patterns and Refactoring Singleton Oliver Haase HTWG Konstanz Oliver Haase (HTWG Konstanz) Design Patterns

Singleton – Additional Considerations

p u b l i c s t a t i c synchron ized vo id c o n f i g ( i n t s t a t e )throws Excep t i on {

i f ( c o n f i g u r e d ) {throw new Excep t i on ( ” a l r e a d y c o n f i g u r e d ” ) ;

}i n s t a n c e . s t a t e = s t a t e ;c o n f i g u r e d = t rue ;

}

p u b l i c s t a t i c CS4 g e t I n s t a n c e ( ) throws Excep t i on {i f ( ! c o n f i g u r e d )

throw new Excep t i on ( ” not c o n f i g u r e d ye t ” ) ;r e t u r n i n s t a n c e ;

}}

Oliver Haase (HTWG Konstanz) Design Patterns and Refactoring 19 / 19