Android Design Patterns Interview Questions

Factory, Singleton, Observer, and more.

50 questions in this topic · 8 sample questions below

Practice Design Patterns in the quiz engine

Sample questions

  1. In Kotlin, what is the most idiomatic way to implement the Singleton pattern?

    • Declare an object instead of a class — correct
    • Use a class with a private constructor and a companion getInstance() with double-checked locking
    • Annotate a class with @Singleton
    • Make all members of the class static using @JvmStatic

    Why: A Kotlin object declaration creates a single, thread-safely instantiated instance managed by the JVM class loader. The manual double-checked-locking approach is the Java idiom and is unnecessary boilerplate in Kotlin.

  2. A colleague claims a Kotlin object is not a real Singleton because it can be instantiated reflectively. What is the accurate assessment?

    • Correct; object declarations expose a public constructor for reflection
    • A Kotlin object is a proper Singleton with a private constructor, initialized lazily and thread-safely on first access — correct
    • It is not a Singleton because each thread gets its own instance
    • It is only a Singleton if you also make it implement Serializable

    Why: An object declaration compiles to a class with a private constructor and a single INSTANCE field created safely by the JVM on first class-load. The reflection claim is a general Java caveat, not something that invalidates object as the standard Singleton.

  3. Why is double-checked locking largely irrelevant when using a Kotlin object for lazy singleton initialization?

    • Because objects are eagerly created at application startup
    • Because Kotlin objects cannot be accessed from multiple threads
    • Because the JVM guarantees thread-safe, lazy class initialization on first access, so no manual locking is needed — correct
    • Because the volatile keyword is applied automatically to all object fields

    Why: The class-initialization lock provided by the JVM guarantees a single, safe initialization the first time the object is referenced. Objects are not eagerly created at startup; they are initialized on first access.

  4. You need a value computed once, lazily, and safely across threads inside a class. Which is the idiomatic Kotlin choice?

    • lateinit var initialized in a synchronized block
    • A companion object holding a volatile nullable field with manual null checks
    • A top-level val computed at file load
    • by lazy { } with the default LazyThreadSafetyMode.SYNCHRONIZED — correct

    Why: Delegated lazy defaults to SYNCHRONIZED mode, computing the value once even under concurrent access. lateinit cannot be used with val or primitive types and provides no lazy computation or thread safety.

  5. Which statement about LazyThreadSafetyMode.PUBLICATION is correct?

    • The initializer may run on multiple threads concurrently, but only the first computed result is published and used — correct
    • The initializer is guaranteed to run exactly once
    • It disables all synchronization, like NONE
    • It blocks all threads until the first one finishes computing

    Why: PUBLICATION allows several threads to race through the initializer, but a compare-and-set ensures only the first successfully published value is retained. SYNCHRONIZED is the mode that guarantees a single execution while blocking others.

  6. The Builder pattern is often said to be redundant in Kotlin. When is a Builder still genuinely useful over named/default arguments?

    • Never; named and default arguments always fully replace it
    • When the object must be constructed incrementally by external/Java callers or through a fluent staged API with validation between steps — correct
    • Only when the class has fewer than three parameters
    • Whenever the class is a data class

    Why: Builders remain valuable for Java interop, staged/step builders, and accumulating state across calls before a final build with validation. The blanket claim that default args always replace Builder ignores these interop and incremental-construction cases.

  7. Which Kotlin feature most directly replaces a hand-written Prototype pattern for immutable data classes?

    • The clone() method from Cloneable
    • Reflection-based deep copy
    • The copy() function generated for data classes — correct
    • The by keyword for delegation

    Why: data class copy() produces a new instance with selected properties overridden, which is exactly the intent of Prototype for value objects. Cloneable/clone() is the Java mechanism and is discouraged in idiomatic Kotlin.

  8. A key caveat when relying on data class copy() as a Prototype is:

    • copy() performs a deep clone of all nested objects
    • copy() only works if the class implements Cloneable
    • copy() ignores default values of constructor parameters
    • copy() is a shallow copy, so mutable nested objects are shared between the original and the copy — correct

    Why: copy() copies references, so a mutable list or object held by the original is shared with the copy, risking aliasing bugs. It does not deep-clone, which is the classic Prototype pitfall.

Practice all 50 Design Patterns questions

These 8 are a sample. The full Design Patterns bank is scored, tracks your progress, and explains every answer.

Open the quiz

More Android interview topics