SlideShare a Scribd company logo
The Singleton
Pattern in Java
1
What is the Singleton Pattern?
• A commonly used idiom to create and maintain objects called
singletons
• A singleton is the only instance of a class
• Common use cases:
• A user’s preferences in a desktop application
• Cache
• Resource pool
2
Example: interface for fetching weather from
an external web service
interface WeatherFetcher {
String fetchWeather(String cityCode) throws IOException;
int fetchTemperature(String cityCode) throws IOException;
}
• Imagine that we are working on a feature which uses this interface
• We need to maintain a connection pool in order to reduce latency
• We want to make sure that we will have only one connection pool, which is
a good use case for the Singleton pattern
3
Singleton which maintains the connection pool
public class SimpleSingleton implements WeatherFetcher {
private static final SimpleSingleton INSTANCE = new SimpleSingleton();
public static WeatherFetcher getInstance() { return INSTANCE; }
private SimpleSingleton() { System.out.println("Populating the connection pool..."); }
@Override public int fetchTemperature(String cityCode) {
// gets an idle connection from the pool, sends a request
return 71; // please assume it's from a response
}
@Override public String fetchWeather(String cityCode) {
// gets an idle connection from the pool, sends a request
return "Sunny"; // please assume it's from a response
}
// client code
public static void main(String[] args) throws IOException {
WeatherFetcher singleton = SimpleSingleton.getInstance();
System.out.printf("Weather in New York: %s, %dFn",
singleton.fetchWeather("NewYork"), singleton.fetchTemperature("NewYork"));
}
} 4
Another requirement: defer initialization until
it’s really necessary
public static void main(String[] args) throws IOException {
System.out.println("Doing some other stuff - I don't need the connection pool yet"); // added
WeatherFetcher singleton = SimpleSingleton.getInstance();
System.out.printf("Weather in New York: %s, %dFn",
singleton.fetchWeather("NewYork"), singleton.fetchTemperature("NewYork"));
}
// The main method yields the following output:
Populating the connection pool...
Doing some other stuff - I don't need the connection pool yet
Weather in New York: Sunny, 71F
• SimpleSingleton’s constructor gets called before the getInstance() call
• Unnecessary resource consumption (initializing the connection pool)
might be imposed on the user 5
Lazy singleton with a static holder class
public class LazySingleton implements WeatherFetcher {
private static class SingletonHolder {
static final LazySingleton INSTANCE = new LazySingleton();
}
public static WeatherFetcher getInstance() { return SingletonHolder.INSTANCE; }
private LazySingleton() { System.out.println("Populating the connection pool..."); }
...
// client code
public static void main(String[] args) throws IOException {
System.out.println("Doing some other stuff - I don't need the connection pool yet");
WeatherFetcher singleton = LazySingleton.getInstance();
System.out.printf("Weather in New York: %s, %dFn",
singleton.fetchWeather("NewYork"), singleton.fetchTemperature("NewYork"));
}
}
// Now the main method yields:
Doing some other stuff - I don't need the connection pool yet
Populating the connection pool...
Weather in New York: Sunny, 71F 6
New requirement: generating a weather report
public class WeatherReporter {
String generateWeatherReport(List<String> cityCodeList) {
StringBuilder sb = new StringBuilder("=== Weather Report ===n");
for (String cityCode : cityCodeList) {
try {
String weather = LazySingleton.getInstance().fetchWeather(cityCode);
int temperature = LazySingleton.getInstance().fetchTemperature(cityCode);
sb.append(String.format("%s: %s, %dFn", cityCode, weather, temperature));
} catch (IOException e) {
sb.append(String.format("%s: Failed to fetch datan", cityCode));
}
}
return sb.toString();
}
}
• Writing unit tests is almost impossible due to static getInstance() calls
• Setting up a data source for testing is too much effort
• Problem: business logic tightly coupled to an external data source
7
Workaround: replacing getInstance() by Supplier
public class ImprovedWeatherReporter {
private final Supplier<? extends WeatherFetcher> weatherFetcherSupplier;
public ImprovedWeatherReporter(Supplier<? extends WeatherFetcher> weatherFetcherSupplier) {
this.weatherFetcherSupplier = weatherFetcherSupplier;
}
String generateWeatherReport(List<String> cityCodeList) {
StringBuilder sb = new StringBuilder("=== Weather Report ===n");
for (String cityCode : cityCodeList) {
try {
String weather = weatherFetcherSupplier.get().fetchWeather(cityCode);
int temperature = weatherFetcherSupplier.get().fetchTemperature(cityCode);
sb.append(String.format("%s: %s, %dFn", cityCode, weather, temperature));
} catch (IOException e) {
sb.append(String.format("%s: Failed to fetch datan", cityCode));
}
}
return sb.toString();
}
}
8
Unit tests for ImprovedWeatherReporter
@ExtendWith(MockitoExtension.class) class ImprovedWeatherReporterTest {
@Mock WeatherFetcher weatherFetcher;
ImprovedWeatherReporter sut;
@BeforeEach void setUp() { sut = new ImprovedWeatherReporter(() -> weatherFetcher); }
@Test void producesReports() throws IOException {
when(weatherFetcher.fetchTemperature("NewYork")).thenReturn(71);
when(weatherFetcher.fetchWeather("NewYork")).thenReturn("Sunny");
when(weatherFetcher.fetchTemperature("Montreal")).thenReturn(68);
when(weatherFetcher.fetchWeather("Montreal")).thenReturn("Cloudy");
String actual = sut.generateWeatherReport(Arrays.asList("NewYork", "Montreal"));
assertThat(actual).isEqualTo("=== Weather Report ===n" +
"NewYork: Sunny, 71Fn" +
"Montreal: Cloudy, 68Fn");
}
@Test void exception() throws IOException {
when(weatherFetcher.fetchTemperature("Tokyo")).thenThrow(new IOException("catch this"));
String actual = sut.generateWeatherReport(Collections.singletonList("Tokyo"));
assertThat(actual).isEqualTo("=== Weather Report ===n" +
"Tokyo: Failed to fetch datan");
}
}
9
Conclusion
• We’ve discussed:
• A couple of common idioms of the Singleton Pattern in Java
• A maintainability issue that can be caused by applying the pattern
• Having getInstance() calls in the middle of business logic can make
code unit test unfriendly
• Introducing a Supplier field instead of getInstance() calls can be a
quick workaround for making code unit test friendly
10

More Related Content

What's hot

Reactive programming with RxAndroid
Reactive programming with RxAndroidReactive programming with RxAndroid
Reactive programming with RxAndroid
Savvycom Savvycom
 
Angular2 rxjs
Angular2 rxjsAngular2 rxjs
Angular2 rxjs
Christoffer Noring
 
Parallel streams in java 8
Parallel streams in java 8Parallel streams in java 8
Parallel streams in java 8
David Gómez García
 
Using Grafana with InfluxDB 2.0 and Flux Lang by Jacob Lisi
Using Grafana with InfluxDB 2.0 and Flux Lang by Jacob LisiUsing Grafana with InfluxDB 2.0 and Flux Lang by Jacob Lisi
Using Grafana with InfluxDB 2.0 and Flux Lang by Jacob Lisi
InfluxData
 
Reactive Java (33rd Degree)
Reactive Java (33rd Degree)Reactive Java (33rd Degree)
Reactive Java (33rd Degree)
Tomasz Kowalczewski
 
Saving lives with rx java
Saving lives with rx javaSaving lives with rx java
Saving lives with rx java
Shahar Barsheshet
 
Rxjs ppt
Rxjs pptRxjs ppt
Extending Flux to Support Other Databases and Data Stores | Adam Anthony | In...
Extending Flux to Support Other Databases and Data Stores | Adam Anthony | In...Extending Flux to Support Other Databases and Data Stores | Adam Anthony | In...
Extending Flux to Support Other Databases and Data Stores | Adam Anthony | In...
InfluxData
 
New text document
New text documentNew text document
New text document
Tam Ngo
 
Apache Flink Training: DataStream API Part 1 Basic
 Apache Flink Training: DataStream API Part 1 Basic Apache Flink Training: DataStream API Part 1 Basic
Apache Flink Training: DataStream API Part 1 Basic
Flink Forward
 
Synapse india dotnet development overloading operater part 4
Synapse india dotnet development overloading operater part 4Synapse india dotnet development overloading operater part 4
Synapse india dotnet development overloading operater part 4
Synapseindiappsdevelopment
 
Asynchronous programming
Asynchronous programmingAsynchronous programming
Asynchronous programming
Filip Ekberg
 
No More Deadlocks; Asynchronous Programming in .NET
No More Deadlocks; Asynchronous Programming in .NETNo More Deadlocks; Asynchronous Programming in .NET
No More Deadlocks; Asynchronous Programming in .NET
Filip Ekberg
 
Streaming Dataflow with Apache Flink
Streaming Dataflow with Apache Flink Streaming Dataflow with Apache Flink
Streaming Dataflow with Apache Flink
huguk
 
Introduction to rx java for android
Introduction to rx java for androidIntroduction to rx java for android
Introduction to rx java for android
Esa Firman
 
Angular and The Case for RxJS
Angular and The Case for RxJSAngular and The Case for RxJS
Angular and The Case for RxJS
Sandi Barr
 
Deep Dumpster Diving
Deep Dumpster DivingDeep Dumpster Diving
Deep Dumpster Diving
RonnBlack
 
Ganga: an interface to the LHC computing grid
Ganga: an interface to the LHC computing gridGanga: an interface to the LHC computing grid
Ganga: an interface to the LHC computing grid
Matt Williams
 
MapReduce wordcount program
MapReduce wordcount program MapReduce wordcount program
MapReduce wordcount program
Sarwan Singh
 
ReactiveCocoa in Practice
ReactiveCocoa in PracticeReactiveCocoa in Practice
ReactiveCocoa in Practice
Outware Mobile
 

What's hot (20)

Reactive programming with RxAndroid
Reactive programming with RxAndroidReactive programming with RxAndroid
Reactive programming with RxAndroid
 
Angular2 rxjs
Angular2 rxjsAngular2 rxjs
Angular2 rxjs
 
Parallel streams in java 8
Parallel streams in java 8Parallel streams in java 8
Parallel streams in java 8
 
Using Grafana with InfluxDB 2.0 and Flux Lang by Jacob Lisi
Using Grafana with InfluxDB 2.0 and Flux Lang by Jacob LisiUsing Grafana with InfluxDB 2.0 and Flux Lang by Jacob Lisi
Using Grafana with InfluxDB 2.0 and Flux Lang by Jacob Lisi
 
Reactive Java (33rd Degree)
Reactive Java (33rd Degree)Reactive Java (33rd Degree)
Reactive Java (33rd Degree)
 
Saving lives with rx java
Saving lives with rx javaSaving lives with rx java
Saving lives with rx java
 
Rxjs ppt
Rxjs pptRxjs ppt
Rxjs ppt
 
Extending Flux to Support Other Databases and Data Stores | Adam Anthony | In...
Extending Flux to Support Other Databases and Data Stores | Adam Anthony | In...Extending Flux to Support Other Databases and Data Stores | Adam Anthony | In...
Extending Flux to Support Other Databases and Data Stores | Adam Anthony | In...
 
New text document
New text documentNew text document
New text document
 
Apache Flink Training: DataStream API Part 1 Basic
 Apache Flink Training: DataStream API Part 1 Basic Apache Flink Training: DataStream API Part 1 Basic
Apache Flink Training: DataStream API Part 1 Basic
 
Synapse india dotnet development overloading operater part 4
Synapse india dotnet development overloading operater part 4Synapse india dotnet development overloading operater part 4
Synapse india dotnet development overloading operater part 4
 
Asynchronous programming
Asynchronous programmingAsynchronous programming
Asynchronous programming
 
No More Deadlocks; Asynchronous Programming in .NET
No More Deadlocks; Asynchronous Programming in .NETNo More Deadlocks; Asynchronous Programming in .NET
No More Deadlocks; Asynchronous Programming in .NET
 
Streaming Dataflow with Apache Flink
Streaming Dataflow with Apache Flink Streaming Dataflow with Apache Flink
Streaming Dataflow with Apache Flink
 
Introduction to rx java for android
Introduction to rx java for androidIntroduction to rx java for android
Introduction to rx java for android
 
Angular and The Case for RxJS
Angular and The Case for RxJSAngular and The Case for RxJS
Angular and The Case for RxJS
 
Deep Dumpster Diving
Deep Dumpster DivingDeep Dumpster Diving
Deep Dumpster Diving
 
Ganga: an interface to the LHC computing grid
Ganga: an interface to the LHC computing gridGanga: an interface to the LHC computing grid
Ganga: an interface to the LHC computing grid
 
MapReduce wordcount program
MapReduce wordcount program MapReduce wordcount program
MapReduce wordcount program
 
ReactiveCocoa in Practice
ReactiveCocoa in PracticeReactiveCocoa in Practice
ReactiveCocoa in Practice
 

Similar to The Singleton Pattern In Java

GDG Jakarta Meetup - Streaming Analytics With Apache Beam
GDG Jakarta Meetup - Streaming Analytics With Apache BeamGDG Jakarta Meetup - Streaming Analytics With Apache Beam
GDG Jakarta Meetup - Streaming Analytics With Apache Beam
Imre Nagi
 
分散式系統
分散式系統分散式系統
分散式系統
acksinkwung
 
Parallel Processing
Parallel ProcessingParallel Processing
Parallel Processing
RTigger
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJava
Frank Lyaruu
 
Architecture components - IT Talk
Architecture components - IT TalkArchitecture components - IT Talk
Architecture components - IT Talk
Constantine Mars
 
Architecture Components
Architecture Components Architecture Components
Architecture Components
DataArt
 
Java Concurrency
Java ConcurrencyJava Concurrency
Java Concurrency
Carol McDonald
 
Android dev 3
Android dev 3Android dev 3
Android dev 3
Aravindharamanan S
 
13multithreaded Programming
13multithreaded Programming13multithreaded Programming
13multithreaded Programming
Adil Jafri
 
srgoc
srgocsrgoc
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoin
knight1128
 
Observer & singleton pattern
Observer  & singleton patternObserver  & singleton pattern
Observer & singleton pattern
babak danyal
 
Tool Development 07 - Undo & Redo, Drag & Drop
Tool Development 07 - Undo & Redo, Drag & DropTool Development 07 - Undo & Redo, Drag & Drop
Tool Development 07 - Undo & Redo, Drag & Drop
Nick Pruehs
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
Tomek Kaczanowski
 
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
First Tuesday Bergen
 
Dependency Injection for Android
Dependency Injection for AndroidDependency Injection for Android
Dependency Injection for Android
First Tuesday Bergen
 
Androidの本当にあった怖い話
Androidの本当にあった怖い話Androidの本当にあった怖い話
Androidの本当にあった怖い話
Yusuke Yamamoto
 
Getting started with TDD - Confoo 2014
Getting started with TDD - Confoo 2014Getting started with TDD - Confoo 2014
Getting started with TDD - Confoo 2014
Eric Hogue
 
12advanced Swing
12advanced Swing12advanced Swing
12advanced Swing
Adil Jafri
 
Building Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJavaBuilding Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJava
Rick Warren
 

Similar to The Singleton Pattern In Java (20)

GDG Jakarta Meetup - Streaming Analytics With Apache Beam
GDG Jakarta Meetup - Streaming Analytics With Apache BeamGDG Jakarta Meetup - Streaming Analytics With Apache Beam
GDG Jakarta Meetup - Streaming Analytics With Apache Beam
 
分散式系統
分散式系統分散式系統
分散式系統
 
Parallel Processing
Parallel ProcessingParallel Processing
Parallel Processing
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJava
 
Architecture components - IT Talk
Architecture components - IT TalkArchitecture components - IT Talk
Architecture components - IT Talk
 
Architecture Components
Architecture Components Architecture Components
Architecture Components
 
Java Concurrency
Java ConcurrencyJava Concurrency
Java Concurrency
 
Android dev 3
Android dev 3Android dev 3
Android dev 3
 
13multithreaded Programming
13multithreaded Programming13multithreaded Programming
13multithreaded Programming
 
srgoc
srgocsrgoc
srgoc
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoin
 
Observer & singleton pattern
Observer  & singleton patternObserver  & singleton pattern
Observer & singleton pattern
 
Tool Development 07 - Undo & Redo, Drag & Drop
Tool Development 07 - Undo & Redo, Drag & DropTool Development 07 - Undo & Redo, Drag & Drop
Tool Development 07 - Undo & Redo, Drag & Drop
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
 
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
 
Dependency Injection for Android
Dependency Injection for AndroidDependency Injection for Android
Dependency Injection for Android
 
Androidの本当にあった怖い話
Androidの本当にあった怖い話Androidの本当にあった怖い話
Androidの本当にあった怖い話
 
Getting started with TDD - Confoo 2014
Getting started with TDD - Confoo 2014Getting started with TDD - Confoo 2014
Getting started with TDD - Confoo 2014
 
12advanced Swing
12advanced Swing12advanced Swing
12advanced Swing
 
Building Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJavaBuilding Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJava
 

More from Kohei Nozaki

The State Pattern
The State PatternThe State Pattern
The State Pattern
Kohei Nozaki
 
Synchronize access to shared mutable data
Synchronize access to shared mutable dataSynchronize access to shared mutable data
Synchronize access to shared mutable data
Kohei Nozaki
 
Favor composition over inheritance
Favor composition over inheritanceFavor composition over inheritance
Favor composition over inheritance
Kohei Nozaki
 
Java Generics wildcards
Java Generics wildcardsJava Generics wildcards
Java Generics wildcards
Kohei Nozaki
 
JUnit and Mockito tips
JUnit and Mockito tipsJUnit and Mockito tips
JUnit and Mockito tips
Kohei Nozaki
 
Overview of Java EE
Overview of Java EEOverview of Java EE
Overview of Java EE
Kohei Nozaki
 

More from Kohei Nozaki (6)

The State Pattern
The State PatternThe State Pattern
The State Pattern
 
Synchronize access to shared mutable data
Synchronize access to shared mutable dataSynchronize access to shared mutable data
Synchronize access to shared mutable data
 
Favor composition over inheritance
Favor composition over inheritanceFavor composition over inheritance
Favor composition over inheritance
 
Java Generics wildcards
Java Generics wildcardsJava Generics wildcards
Java Generics wildcards
 
JUnit and Mockito tips
JUnit and Mockito tipsJUnit and Mockito tips
JUnit and Mockito tips
 
Overview of Java EE
Overview of Java EEOverview of Java EE
Overview of Java EE
 

Recently uploaded

SMS API Integration in Saudi Arabia| Best SMS API Service
SMS API Integration in Saudi Arabia| Best SMS API ServiceSMS API Integration in Saudi Arabia| Best SMS API Service
SMS API Integration in Saudi Arabia| Best SMS API Service
Yara Milbes
 
Unveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdfUnveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdf
brainerhub1
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Julian Hyde
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
Hornet Dynamics
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
lorraineandreiamcidl
 
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdfRevolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Undress Baby
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
Green Software Development
 
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s EcosystemUI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
Peter Muessig
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf
kalichargn70th171
 
Webinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for EmbeddedWebinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for Embedded
ICS
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
Green Software Development
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
Grant Fritchey
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
Aftab Hussain
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Łukasz Chruściel
 

Recently uploaded (20)

SMS API Integration in Saudi Arabia| Best SMS API Service
SMS API Integration in Saudi Arabia| Best SMS API ServiceSMS API Integration in Saudi Arabia| Best SMS API Service
SMS API Integration in Saudi Arabia| Best SMS API Service
 
Unveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdfUnveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdf
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
 
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdfRevolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
 
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s EcosystemUI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf
 
Webinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for EmbeddedWebinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for Embedded
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
 

The Singleton Pattern In Java

  • 2. What is the Singleton Pattern? • A commonly used idiom to create and maintain objects called singletons • A singleton is the only instance of a class • Common use cases: • A user’s preferences in a desktop application • Cache • Resource pool 2
  • 3. Example: interface for fetching weather from an external web service interface WeatherFetcher { String fetchWeather(String cityCode) throws IOException; int fetchTemperature(String cityCode) throws IOException; } • Imagine that we are working on a feature which uses this interface • We need to maintain a connection pool in order to reduce latency • We want to make sure that we will have only one connection pool, which is a good use case for the Singleton pattern 3
  • 4. Singleton which maintains the connection pool public class SimpleSingleton implements WeatherFetcher { private static final SimpleSingleton INSTANCE = new SimpleSingleton(); public static WeatherFetcher getInstance() { return INSTANCE; } private SimpleSingleton() { System.out.println("Populating the connection pool..."); } @Override public int fetchTemperature(String cityCode) { // gets an idle connection from the pool, sends a request return 71; // please assume it's from a response } @Override public String fetchWeather(String cityCode) { // gets an idle connection from the pool, sends a request return "Sunny"; // please assume it's from a response } // client code public static void main(String[] args) throws IOException { WeatherFetcher singleton = SimpleSingleton.getInstance(); System.out.printf("Weather in New York: %s, %dFn", singleton.fetchWeather("NewYork"), singleton.fetchTemperature("NewYork")); } } 4
  • 5. Another requirement: defer initialization until it’s really necessary public static void main(String[] args) throws IOException { System.out.println("Doing some other stuff - I don't need the connection pool yet"); // added WeatherFetcher singleton = SimpleSingleton.getInstance(); System.out.printf("Weather in New York: %s, %dFn", singleton.fetchWeather("NewYork"), singleton.fetchTemperature("NewYork")); } // The main method yields the following output: Populating the connection pool... Doing some other stuff - I don't need the connection pool yet Weather in New York: Sunny, 71F • SimpleSingleton’s constructor gets called before the getInstance() call • Unnecessary resource consumption (initializing the connection pool) might be imposed on the user 5
  • 6. Lazy singleton with a static holder class public class LazySingleton implements WeatherFetcher { private static class SingletonHolder { static final LazySingleton INSTANCE = new LazySingleton(); } public static WeatherFetcher getInstance() { return SingletonHolder.INSTANCE; } private LazySingleton() { System.out.println("Populating the connection pool..."); } ... // client code public static void main(String[] args) throws IOException { System.out.println("Doing some other stuff - I don't need the connection pool yet"); WeatherFetcher singleton = LazySingleton.getInstance(); System.out.printf("Weather in New York: %s, %dFn", singleton.fetchWeather("NewYork"), singleton.fetchTemperature("NewYork")); } } // Now the main method yields: Doing some other stuff - I don't need the connection pool yet Populating the connection pool... Weather in New York: Sunny, 71F 6
  • 7. New requirement: generating a weather report public class WeatherReporter { String generateWeatherReport(List<String> cityCodeList) { StringBuilder sb = new StringBuilder("=== Weather Report ===n"); for (String cityCode : cityCodeList) { try { String weather = LazySingleton.getInstance().fetchWeather(cityCode); int temperature = LazySingleton.getInstance().fetchTemperature(cityCode); sb.append(String.format("%s: %s, %dFn", cityCode, weather, temperature)); } catch (IOException e) { sb.append(String.format("%s: Failed to fetch datan", cityCode)); } } return sb.toString(); } } • Writing unit tests is almost impossible due to static getInstance() calls • Setting up a data source for testing is too much effort • Problem: business logic tightly coupled to an external data source 7
  • 8. Workaround: replacing getInstance() by Supplier public class ImprovedWeatherReporter { private final Supplier<? extends WeatherFetcher> weatherFetcherSupplier; public ImprovedWeatherReporter(Supplier<? extends WeatherFetcher> weatherFetcherSupplier) { this.weatherFetcherSupplier = weatherFetcherSupplier; } String generateWeatherReport(List<String> cityCodeList) { StringBuilder sb = new StringBuilder("=== Weather Report ===n"); for (String cityCode : cityCodeList) { try { String weather = weatherFetcherSupplier.get().fetchWeather(cityCode); int temperature = weatherFetcherSupplier.get().fetchTemperature(cityCode); sb.append(String.format("%s: %s, %dFn", cityCode, weather, temperature)); } catch (IOException e) { sb.append(String.format("%s: Failed to fetch datan", cityCode)); } } return sb.toString(); } } 8
  • 9. Unit tests for ImprovedWeatherReporter @ExtendWith(MockitoExtension.class) class ImprovedWeatherReporterTest { @Mock WeatherFetcher weatherFetcher; ImprovedWeatherReporter sut; @BeforeEach void setUp() { sut = new ImprovedWeatherReporter(() -> weatherFetcher); } @Test void producesReports() throws IOException { when(weatherFetcher.fetchTemperature("NewYork")).thenReturn(71); when(weatherFetcher.fetchWeather("NewYork")).thenReturn("Sunny"); when(weatherFetcher.fetchTemperature("Montreal")).thenReturn(68); when(weatherFetcher.fetchWeather("Montreal")).thenReturn("Cloudy"); String actual = sut.generateWeatherReport(Arrays.asList("NewYork", "Montreal")); assertThat(actual).isEqualTo("=== Weather Report ===n" + "NewYork: Sunny, 71Fn" + "Montreal: Cloudy, 68Fn"); } @Test void exception() throws IOException { when(weatherFetcher.fetchTemperature("Tokyo")).thenThrow(new IOException("catch this")); String actual = sut.generateWeatherReport(Collections.singletonList("Tokyo")); assertThat(actual).isEqualTo("=== Weather Report ===n" + "Tokyo: Failed to fetch datan"); } } 9
  • 10. Conclusion • We’ve discussed: • A couple of common idioms of the Singleton Pattern in Java • A maintainability issue that can be caused by applying the pattern • Having getInstance() calls in the middle of business logic can make code unit test unfriendly • Introducing a Supplier field instead of getInstance() calls can be a quick workaround for making code unit test friendly 10