Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
The Abstract Factory is a software design pattern whose goal is to provide a single interface to create families of objects with the same theme but without exposing the concrete implementation. This pattern provides another layer of abstraction over the factory pattern.
In this tutorial, we’ll look at an efficient approach for the implementation of the Abstract Factory in Kotlin.
The Abstract Factory is a creational design pattern and the main purpose is to encapsulate the creation of objects with a common theme in a separate factory object. In addition, each factory object has the responsibility of providing building services for all objects.
Let’s take a look at the component classes and interfaces of the Abstract Factory:
The following diagram shows the structure of an Abstract Factory along with its components:
For our case of study, let’s consider the example of a family of weapons. For that, we’ll need a way to create objects of type Weapon that can be used on the client-side.
Let’s define the common generic interface for the type Weapon:
interface Weapon {
fun use():String
}
Next, we’ll create the abstract factory class that will serve as the generic interface for creating objects of type Weapon:
abstract class WeaponFactory {
abstract fun buildWeapon(): Weapon
}
For this tutorial, we’ll use companion objects to implement the specific factories. Companion objects in Kotlin allow creating objects declared in the same file as a class. For instance, we can define a companion object Factory for each specific weapon we might need.
Let’s now create the Crossbow class:
class Crossbow : Weapon {
companion object Factory : WeaponFactory() {
override fun buildWeapon() = Crossbow()
}
override fun use(): String {
return "Using crossbow weapon"
}
}
After that, we just need to define the final client for this type of weapon:
val factory : WeaponFactory = Crossbow.Factory
val crossbow = factory.buildWeapon()
assertNotNull(crossbow)
assertEquals("Using crossbow weapon", crossbow.use())
We can see that the Weapon type is defined at runtime through the Factory declaration.
Similarly, we can also define another type of Weapon. Let’s define a type of sword – the Katana:
class Katana : Weapon {
companion object Factory : WeaponFactory() {
override fun buildWeapon() = Katana()
}
override fun use(): String {
return "Using katana weapon"
}
}
Implementing the Abstract Factory pattern can result in a more complicated code to maintain. However, there are some advantages of using this pattern:
In this article, we’ve explored an efficient approach to implement the Abstract Factory pattern in Kotlin. This pattern is useful when we need another level of abstraction over a group of factories. In addition, we saw that Kotlin offers great support for implementing the pattern.