Design Patterns in Android Development

Design patterns are proven solutions to common problems in software design. They help structure code, improve reusability, and maintain consistency. Below, we explore various design patterns and their applications in Android development.

🏗️ Singleton Pattern

This pattern ensures a single instance of a class. Common use cases in Android include SharedPreferences, Retrofit, and Room database instances.

Example:

object RetrofitInstance {
    val retrofit: Retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .build()
}

👷 Builder Pattern

The Builder Pattern helps construct complex objects step by step. In Android, AlertDialog.Builder or Notification.Builder are great examples.

Example:

val alertDialog = AlertDialog.Builder(this)
    .setTitle("Title")
    .setMessage("Message")
    .setPositiveButton("OK", null)
    .create()
alertDialog.show()

📢 Observer Pattern

The Observer Pattern is used to notify observers of changes. In Android, LiveData is commonly used.

Example:

viewModel.liveData.observe(this) { data ->
    textView.text = data
}

📊 Repository Pattern

This pattern abstracts data sources and provides a clean API. It’s widely used with Room and Retrofit.

Example:

class Repository(private val api: ApiService, private val dao: Dao) {
    fun fetchData() = api.getData()
    fun saveData(data: List<Data>) = dao.insertAll(data)
}

📡 Repository + UseCase Pattern

Combine Repository and UseCase patterns for better separation of concerns.

Example:

class GetUserUseCase(private val repository: UserRepository) {
    fun execute() = repository.getUser()
}

🏭 Factory Pattern

The Factory Pattern is used to create objects without specifying the exact class. In Android, FragmentFactory can be used to dynamically create fragments.

Example:

class CustomFragmentFactory : FragmentFactory() {
    override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
        return when (className) {
            MyFragment::class.java.name -> MyFragment(arguments)
            else -> super.instantiate(classLoader, className)
        }
    }
}

🧳 Prototype Pattern

The Prototype Pattern involves cloning objects to avoid expensive object creation. In Android, you can use this pattern for UI elements.

Example:

val originalView = TextView(context)
val clonedView = originalView.copy()

🧩 Adapter Pattern

This pattern converts one interface into another. The RecyclerView.Adapter is a common example in Android.

Example:

class MyAdapter(private val data: List<String>) : RecyclerView.Adapter<MyViewHolder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_view, parent, false)
        return MyViewHolder(view)
    }
    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.bind(data[position])
    }
    override fun getItemCount() = data.size
}

🏰 Facade Pattern

The Facade Pattern provides a simplified interface to a larger, more complex system. MediaPlayer in Android is a great example.

Example:

val mediaPlayer = MediaPlayer().apply {
    setDataSource("audio_file.mp3")
    prepare()
    start()
}

🛠️ Decorator Pattern

This pattern dynamically adds functionality to an object. Wrapping InputStream in BufferedInputStream is an example.

Example:

val inputStream = FileInputStream(file)
val bufferedStream = BufferedInputStream(inputStream)

🌉 Bridge Pattern

The Bridge Pattern decouples abstraction from implementation. In Android, it can be seen in custom views.

Example:

class CustomView(context: Context) : View(context) {
    override fun onDraw(canvas: Canvas) {
        // Custom drawing logic
    }
}

🏗️ Composite Pattern

This pattern composes objects into tree structures. The ViewGroup and View hierarchy in Android are examples.

Example:

val linearLayout = LinearLayout(context).apply {
    orientation = LinearLayout.VERTICAL
    addView(TextView(context))
    addView(Button(context))
}

👥 Strategy Pattern

This pattern defines a family of algorithms and lets you choose one at runtime. In Android, it is used for handling different UI states.

Example:

val strategy = if (isTablet) TabletLayoutStrategy() else PhoneLayoutStrategy()
strategy.applyLayout()

💡 Command Pattern

The Command Pattern encapsulates user actions as objects. Button clicks in Android can follow this pattern.

Example:

val command = ClickCommand(Button(context))
command.execute()

🧲 Memento Pattern

The Memento Pattern saves an object’s state. SavedStateHandle in ViewModel is an example.

Example:

class MyViewModel(private val state: SavedStateHandle) : ViewModel() {
    val data = state.getLiveData("key")
}

🔄 State Pattern

The State Pattern manages state-dependent behavior. In Android, it can be used for media player states.

Example:

class MediaPlayerState {
    fun play() { /* ... */ }
    fun pause() { /* ... */ }
}

💻 Service Locator Pattern

Simplify dependency lookup for services like LocationManager or NotificationManager.

Example:

val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager

Note: You don’t have to memorize all these patterns by heart. Focus on understanding the core principles and applying them when needed in your projects. It’s a journey, not a race!

Akshay Nandwana
Founder AndroidEngineers

You can connect with me on:


Book 1:1 Session here
Click Here

Join our upcoming classes
https://www.androidengineers.in/courses

Love from our past students

Excellent list of questions really helped me to coverup all the topics before interview.

Saiteja Janjirala

10th Oct, 2024

I had an exceptional experience with the 1:1 mentorship session. Akshay was incredibly friendly and provided invaluable guidance on focusing on long-term goals. They also gave great interview tips, including a thorough resume review. Additionally, the discussion on Data Structures and Algorithms (DSA) was insightful and practical. Highly recommended for anyone looking to advance their career!

Nayab khan

11th Sep, 2024

Cleared my major points for what I am missing in the resume and also suggested what I can work on for further growth in the career.

Ketan Chaurasiya

7th Aug, 2024

What impressed me most was his personalized approach and practical tips that I could immediately apply. Akshay’s guidance not only improved my technical skills but also boosted my confidence in navigating my career path. His insights and encouragement have been a game-changer for me. I highly recommend Akshay’s mentorship to anyone looking to advance their Android development career.

Hardik Kubavat

5th Aug, 2024

2025© Made with   by Android Engineers.