Mastering Creational Design Patterns in Kotlin & Android: Singleton, Factory & Abstract Factory
Introduction
Mastering Creational Design Patterns in Kotlin & Android: Singleton, Factory & Abstract Factory
Introduction
Object creation in software development can become complex and inefficient if not handled properly. Hardcoded object creation leads to tightly coupled code, making maintenance, testing, and scalability difficult.
This is where Creational Design Patterns help by providing flexible and efficient object creation mechanisms.
Why Learn Creational Design Patterns?
✅ Better Object Management — Avoid unnecessary object creation. ✅ Loose Coupling — Reduces dependency between components. ✅ Scalability — Makes it easier to add new types without modifying existing code. ✅ Testability — Simplifies unit testing and mocking dependencies.
This guide covers: 🔹 Singleton Pattern — Ensures only one instance of a class exists. 🔹 Factory Pattern — Creates objects without exposing creation logic. 🔹 Abstract Factory Pattern — Provides a higher-level abstraction for object creation.
Let’s dive into Creational Patterns and explore how to implement them in Kotlin and Android. 🚀
1️⃣ Singleton Pattern
What is the Singleton Pattern?
Singleton ensures that only one instance of a class exists throughout the application and provides a global access point to that instance.
✅ Key Features: ✔ Single Instance — Only one object exists in memory. ✔ Global Access Point — The instance is accessible from anywhere. ✔ Thread Safety — Ensures safe multi-threaded access.
When to Use Singleton?
✔ When only one instance of a class is needed across the app. ✔ To prevent multiple resource-heavy instances (e.g., database connections, network calls). ✔ For shared state or cache management.
How to Identify the Need for Singleton?
🔹 If you see multiple objects holding the same state, Singleton can centralize that state. 🔹 If an object must be shared globally (e.g., database, logging system).
Singleton in Kotlin (Implementation & Test)
object NetworkDriver {
init {
println("Network Driver Initialized: $this")
}
fun log(): NetworkDriver = apply { println("Logging from: $this") }
}
class SingletonTest {
@Test
fun testSingleton() {
println("Start Singleton Test")
val networkDriver1 = NetworkDriver.log()
val networkDriver2 = NetworkDriver.log()
assertThat(networkDriver1).isSameAs(NetworkDriver)
assertThat(networkDriver2).isSameAs(NetworkDriver)
}
}
Alternative Ways to Implement Singleton in Kotlin
1️⃣ Using Lazy Initialization
class Database private constructor() {
companion object {
val instance: Database by lazy { Database() }
}
}
2️⃣ Using Synchronized Block (Thread-safe Singleton)
class Logger private constructor() {
companion object {
@Volatile
private var instance: Logger? = null
fun getInstance(): Logger {
return instance ?: synchronized(this) {
instance ?: Logger().also { instance = it }
}
}
}
}
✅ Android Use Cases: ✔ SharedPreferences management ✔ Database instance (Room Database) ✔ Networking (Retrofit instance)
2️⃣ Factory Pattern
What is the Factory Pattern?
Factory Pattern provides a way to create objects without exposing creation logic. Instead of using new, it delegates object creation to a factory method.
✅ Key Features: ✔ Encapsulates object creation logic. ✔ Promotes loose coupling. ✔ Improves testability and maintainability.
When to Use Factory Pattern?
✔ When multiple subclasses share a common interface but need different implementations. ✔ When object creation depends on user input or runtime conditions. ✔ When you don’t want clients to directly instantiate objects.
How to Identify the Need for Factory?
🔹 If object creation logic varies based on input, consider a Factory.
🔹 If you see when or if-else blocks used for instantiating classes, Factory helps reduce repetition.
Factory in Kotlin (Implementation & Test)
sealed class Country {
object Canada : Country()
object Spain : Country()
class Greece(val prop: String) : Country()
data class USA(val prop: String) : Country()
}
class Currency(val code: String)
object CurrencyFactory {
fun currencyForCountry(country: Country): Currency =
when (country) {
is Country.Spain -> Currency("EUR")
is Country.USA -> Currency("USD")
is Country.Greece -> Currency("EUR")
is Country.Canada -> Currency("CAD")
}
}
class FactoryMethodTest {
@Test
fun currencyTest() {
val greeceCurrency = CurrencyFactory.currencyForCountry(Country.Greece("")).code
val usaCurrency = CurrencyFactory.currencyForCountry(Country.USA("")).code
assertThat(greeceCurrency).isEqualTo("EUR")
assertThat(usaCurrency).isEqualTo("USD")
}
}
✅ Android Use Cases: ✔ ViewModel Factory (Creating ViewModels dynamically) ✔ UI Component Factories (Button, AlertDialog, RecyclerView Adapters)
Using Factory Pattern for ViewModel Factory in Android
In Android MVVM architecture, we often need to create instances of ViewModel classes with dependencies. However, ViewModels do not have default constructors, so ViewModelProviders require a custom ViewModelFactory to instantiate them properly.
Custom ViewModel Factory Implementation in Kotlin
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
// ViewModel that requires dependencies
class UserViewModel(private val repository: UserRepository) : ViewModel() {
fun getUserData(): String = repository.getUser()
}
// ViewModel Factory using Factory Pattern
class ViewModelFactory(private val repository: UserRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(UserViewModel::class.java)) {
return UserViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
// Example Usage
val factory = ViewModelFactory(UserRepository())
val userViewModel = ViewModelProvider(viewModelStore, factory).get(UserViewModel::class.java)
✅ Benefits of Using Factory Pattern for ViewModels: ✔ Decouples ViewModel instantiation from UI components. ✔ Enables dependency injection. ✔ Makes testing ViewModels easier.
3️⃣ Abstract Factory Pattern
What is the Abstract Factory Pattern?
Abstract Factory adds an extra layer of abstraction over the Factory Pattern. It provides a way to create families of related objects without specifying their concrete classes.
✅ Key Features: ✔ Encapsulates multiple factories. ✔ Allows easy swapping of object families. ✔ Promotes scalability and testability.
When to Use Abstract Factory?
✔ When an application needs multiple factories for creating related objects. ✔ When object creation must be handled dynamically. ✔ When you need flexibility to switch between object families.
Abstract Factory in Kotlin (Implementation & Test)
interface DataSource
class DataBaseDataSource : DataSource
class NetworkDataSource : DataSource
abstract class DataSourceFactory {
abstract fun makeDataSource(): DataSource
companion object {
inline fun <reified T : DataSource> createFactory(): DataSourceFactory =
when (T::class) {
DataBaseDataSource::class -> DataBaseFactory()
NetworkDataSource::class -> NetworkFactory()
else -> throw IllegalArgumentException()
}
}
}
class DataBaseFactory : DataSourceFactory() {
override fun makeDataSource() = DataBaseDataSource()
}
class NetworkFactory : DataSourceFactory() {
override fun makeDataSource() = NetworkDataSource()
}
class AbstractFactoryTest {
@Test
fun abstractFactoryTest() {
val dataSourceFactory = DataSourceFactory.createFactory<DataBaseDataSource>()
val dataSource = dataSourceFactory.makeDataSource()
assertThat(dataSource).isInstanceOf(DataBaseDataSource::class.java)
}
}
✅ Android Use Cases: ✔ Data sources (Local vs. Remote databases) ✔ Theme-based UI rendering (Light/Dark mode components)
Final Thoughts
The Creational Design Patterns (Singleton, Factory, Abstract Factory) help improve object creation, scalability, and maintainability in Kotlin and Android development.
💡 Try implementing these patterns in your next Kotlin project!
🚀 Follow for more Kotlin and Android design pattern insights!
메타데이터
- post_id
- 41805e6d499d
- slug
- mastering-creational-design-patterns-in-kotlin-android-singleton-factory-abstract-factory-41805e6d499d
- url
- https://medium.com/@chetanshingare2991/mastering-creational-design-patterns-in-kotlin-android-singleton-factory-abstract-factory-41805e6d499d
- canonical_url
- https://medium.com/@chetanshingare2991/mastering-creational-design-patterns-in-kotlin-android-singleton-factory-abstract-factory-41805e6d499d
- author_url
- https://medium.com/@chetanshingare2991
- status
- ok
- fetched_at
- 2026-06-09 15:37:30