0Pricing
Kotlin Academy · Lesson

Factory Methods with companion object

Implement factory patterns using companion object and invoke operator.

Factory Methods with companion object is a free Kotlin Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Kotlin Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

The Factory Method Pattern

Factory methods create objects with meaningful names and logic, hiding constructor complexity. Kotlin's companion object is the ideal home for them.

Private Constructor + Factory

Make the constructor private and provide factory methods via companion object.
class Token private constructor(val value: String) {
    companion object {
        fun generate() = Token(java.util.UUID.randomUUID().toString())
        fun fromString(s: String) = Token(s.trim())
    }
}
val t = Token.generate()

Named Factory Methods

Descriptive names make intent clear — unlike constructor overloads.
class Duration private constructor(val ms: Long) {
    companion object {
        fun ofMillis(ms: Long) = Duration(ms)
        fun ofSeconds(s: Long) = Duration(s * 1000)
        fun ofMinutes(m: Long) = Duration(m * 60_000)
    }
}
val d = Duration.ofMinutes(5)

Returning Null from Factory

Factories can return null for invalid inputs instead of throwing.
class Percentage private constructor(val value: Int) {
    companion object {
        fun of(value: Int): Percentage? {
            return if (value in 0..100) Percentage(value) else null
        }
    }
}
val p = Percentage.of(75) ?: error("Invalid")

Cached Instances

Factories can cache and reuse instances.
class Direction private constructor(val name: String) {
    companion object {
        private val cache = mutableMapOf<String, Direction>()
        fun of(name: String) = cache.getOrPut(name.uppercase()) {
            Direction(name.uppercase())
        }
    }
}

invoke Operator as Constructor-Like Factory

Define invoke() to call the class like a function.
class Email private constructor(val address: String) {
    companion object {
        operator fun invoke(raw: String): Email {
            require("@" in raw) { "Invalid email" }
            return Email(raw.lowercase())
        }
    }
}
val e = Email("Test@Example.com")  // looks like a constructor

Abstract Factory with Sealed Classes

Combine factory methods with sealed class hierarchies for typed creation.
sealed class Shape {
    data class Circle(val r: Double) : Shape()
    data class Rect(val w: Double, val h: Double) : Shape()
    companion object {
        fun circle(r: Double) = Circle(r)
        fun rect(w: Double, h: Double) = Rect(w, h)
    }
}

Dependency-Aware Factory

Factories can accept dependencies and wire them up.
class Repository(private val db: Database) {
    companion object {
        fun create(db: Database = Database.instance) = Repository(db)
    }
    fun findAll() = db.query("SELECT * FROM items")
}

Factory in Tests

Factory methods make test object creation clean and explicit.
class Order private constructor(
    val id: Long, val items: List<String>, val paid: Boolean
) {
    companion object {
        fun unpaid(id: Long, items: List<String>) = Order(id, items, false)
        fun paid(id: Long, items: List<String>) = Order(id, items, true)
    }
}

From JSON/Config

Factories are natural parsing entry points.
class AppConfig private constructor(
    val baseUrl: String, val timeout: Int
) {
    companion object {
        fun fromEnv() = AppConfig(
            baseUrl = System.getenv("BASE_URL") ?: "http://localhost",
            timeout = System.getenv("TIMEOUT")?.toInt() ?: 30
        )
    }
}

When NOT to Use Private Constructor

Don't make constructors private just for style. Use it when: validation is required, caching is needed, or multiple creation paths have distinct semantics.

Quick Check

What operator function allows calling a companion object like a constructor: Email("a@b.com")?

Recap

Factory methods in companion objects: private constructor + named factories, optional null returns, caching, invoke() for constructor-like syntax. Factories make object creation safe, expressive, and testable!

Frequently asked questions

Is the “Factory Methods with companion object” lesson free?

Yes — the full text of “Factory Methods with companion object” is free to read here on the web, and the Kotlin Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Kotlin Academy course, upgrade to CoddyKit PRO.

What will I learn in “Factory Methods with companion object”?

Implement factory patterns using companion object and invoke operator. You practise Kotlin Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Kotlin Academy?

No prior experience is required. Kotlin Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Factory Methods with companion object” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Kotlin Academy lesson?

Yes. Every Kotlin Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. object Declaration: Kotlin Singletons
  2. companion object: Static-like Members in Kotlin
  3. Anonymous Objects and Object Expressions
  4. Factory Methods with companion object
← Back to Kotlin Academy