Factory Design Pattern
Learn about the Factory Design pattern in Kotlin, along with how to create objects without using a constructor.
The Factory Method design pattern is all about creating objects.
But why do we need a method to create objects? Isn’t that what constructors are for?
Well, constructors have limitations. As an example, imagine we’re building a game of chess. We would like to allow our players to save the state of the game into a text file and then restore the game from that position.
Since the size of the board is predetermined, we only need to record the position and type of each piece. We’ll use algebraic notation for this—for example, the Queen piece at C3 will be stored in our file as qc3, the pawn piece at A8 will be stored as pa8, and so on.
Let’s assume that we already read this file into a list of strings. Given the list of notations, we would like to populate our board with them:
// More pieces hereval notations = listOf("pa8", "qc3", ...)val pieces = mutableListOf<ChessPiece>()for (n in notations) {pieces.add(createPiece(n))}println(pieces)
Before we can implement our createPiece
function, we need to decide what’s common to all chess pieces. We’ll create an interface for that:
interface ChessPiece {val file: Charval rank: Char}
Note that interfaces in Kotlin can declare properties, which is a very powerful feature.
Each chess piece will be a data class that implements our interface:
data class Pawn(override val file: Char,override val rank: Char) : ChessPiecedata class Queen(override val file: Char,override val rank: Char) : ChessPiece
We can implement the other chess pieces same as these.
Now, what’s left is to implement our createPiece
function:
fun createPiece(notation: String): ChessPiece {val (type, file, rank) = notation.toCharArray()return when (type) {'q' -> Queen(file, rank)'p' -> Pawn(file, rank)// ...else -> throwRuntimeException("Unknown piece: $type")}}
Before we can discuss what ...