Six design patterns that Android developers must know

Six design patterns that Android developers must know

1 What is a design pattern?

A design pattern is a reusable solution to a software engineering problem. Unlike solutions to many specific programs, design patterns can be applied to many different programs. A design pattern is not a finished product, but a template that can be applied to multiple situations and improved over time. It is a very powerful software engineering tool. Using proven prototypes can increase development speed, and developers who use design pattern templates can improve coding efficiency and the readability of the final product.

2 Pattern #1 đź‘Ś Singleton

The singleton pattern is a class that allows the creation of a unique instance and access to that instance. It contains a private static variable that can hold the only instance of the class. The singleton pattern is often useful when you need to limit the instantiation of a class to one object. The singleton pattern is usually used when you need to coordinate a single object operating in a system.

3 Properties of Singleton Class

  • Only one instance
  • Globally accessible

4 Rules for making singleton classes

Follow these rules to create a singleton class:

  • Private Constructor
  • Static reference to a class
  • A static method
  • Globally accessible object references
  • Multithreaded consistency

5 Singleton Example

Following is an example of Singleton class in Java:

 public class Singleton { private static Singleton instance = null; private Singleton() { } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }

Following is an example of a Singleton class in Kotlin:

 Object Singleton { init { println("Hello Singleton") } }

6 Pattern #2 đź‘Ś Factory Pattern

The factory pattern is a design pattern for creating objects that gets its name from its factory-like behavior. In the factory pattern, the factory class is responsible for controlling the logic of instantiating an object. The factory pattern is useful when you need to create multiple objects with similar behavior. You can use the factory pattern to create objects without specifying a specific class. This makes the code more flexible and easier to modify and maintain.

Please see the following code for better understanding:

 interface Currency { fun symbol(): String fun code(): String } enum class Country { UnitedState, Spain } class USDollar : Currency { override fun symbol(): String { return "$" } override fun code(): String { return "USD" } } class Euro : Currency { override fun symbol(): String { return "€" } override fun code(): String { return "EUR" } } object CurrencyFactory { fun currency(country: Country): Currency { return when (country) { Country.UnitedState -> { USDollar() } Country.Spain -> { Euro() } } } }

7 Pattern #3 đź‘Ś Builder Pattern

The Builder pattern aims to “decouple the construction of a complex object from its representation so that the same construction process can create different representations.” It is used to build a complex object step by step and the last step will return the object.

8 Rules for making Builder classes

The following rules are followed when making a Builder class:

  • Private Constructor
  • Usually called the inner class of Builder
  • The function for each field sets the field value to return
  • The constructor returns an instance of the Main class

Following is an example of a Builder class in Kotlin:

 class Hamburger private constructor( val cheese: Boolean, val beef: Boolean, val onions: Boolean ) { class Builder { private var cheese: Boolean = true private var beef: Boolean = true private var onions: Boolean = true fun cheese(value: Boolean) = apply { cheese = value } fun beef(value: Boolean) = apply { beef = value } fun onions(value: Boolean) = apply { onions = value } fun build() = Hamburger(cheese, beef, onions) } }

9. Pattern #4 đź‘Ś Appearance Pattern

The Facade pattern provides a higher-level interface that makes a set of other interfaces easier to use. It encapsulates the complexity of a set of classes and provides a higher-level interface to simplify access to those classes. The following diagram illustrates this idea more clearly.

 interface BooksApi { @GET("books") fun listBooks(): Call<List<Book>> }

Retrofit by Square is an open source Android library that helps you implement the facade pattern. You can create an interface to provide API data to the client.

10 Pattern #5 đź‘Ś Dependency Injection

Dependency injection is like moving into a fully furnished apartment; everything you need is already there, without having to wait for the furniture to be delivered or follow the furniture company's instruction guide to assemble it.

In software terms, dependency injection requires that you provide any required objects to instantiate a new object. This new object does not need to construct or customize the object itself.

In Android, you may find that you need to access the same complex object from various points in your application, such as a network client, an image loader, or SharedPreferences for local storage. To facilitate access to these objects, you can inject them into activities and fragments and use them directly. This approach is called dependency injection, and it allows you to more easily manage and share objects in your application, and improves code reusability and test reliability.

The following example shows the code for a Car class that does not use dependency injection. In this example, Car class is building its own Engine dependency:

 class Car { private val engine = Engine() fun start() { engine.start() } } fun main(args: Array) { val car = Car() car.start() }

This approach is problematic because Car class has a hard-coded dependency on Engine class, which will make the code difficult to maintain and test. If you need to change the Engine implementation or use a different implementation, you need to modify the code of Car class. This may lead to refactoring and retesting of the code, and may affect other code that depends on Car class. Therefore, using dependency injection can solve this problem and improve the reusability and testability of the code.

What does the code look like using dependency injection? Instead of each Car instance constructing its own Engine object when it is initialized, it receives an Engine object as a parameter in the constructor:

 class Car(private val engine: Engine) { fun start() { engine.start() } } fun main(args: Array) { val engine = Engine() val car = Car(engine) car.start() }

11 Pattern #6 đź‘Ś Adapter Pattern

The adapter pattern is a bridge pattern used to connect two incompatible interfaces.

This pattern involves a single class that is responsible for connecting the functionality of separate or incompatible interfaces. A real-life example might be a card reader that acts as an adapter between a memory card and a laptop. You insert the memory card into the card reader and the card reader into the laptop so that the memory card can be read by the laptop.

<<:  Good news for designers: Apple releases Figma design kit, covering all resources for iOS 17 and iPadOS 17

>>:  Apple strengthens privacy protection, iOS 17 can automatically block tracking parameters on websites

Recommend

The "best lifestyle" for longevity, these 4 factors are the key!

Compiled by: Gong Zixin We know that genetics and...

Inventory of essential tools for new media operations (dry goods collection)

We also need to arrange a good-looking layout How...

How to create a Douyin account? Introduction to Douyin operation methods

Nowadays, short videos are in a very fierce compe...

How to optimize Weibo advertising creativity?

Marketing status: The advertiser is a local O2O d...

Some basic techniques for operation, promotion and attracting new customers!

Operations is a very complex business system. Gen...

What kind of platform is Juliang Qianchuan?

What is Juliang Qianchuan? Bytedance Qianchuan is...

Marketing course-It is important to introduce products to customers step by step

The secret to successful sales is to skillfully l...

Ouch! A mouse is pulling a winter melon!

Audit expert: Li Weiyang Well-known science write...