Abstract Factory and Interface – Kotlin Example
From time to time during job interviews I encountered questions about some design patterns. At the beginning I was quite confused about this topic, because I knew how to write and create medium-scale applications, but from the theoreticial way I was sucked.
If you are a beginner developer, have to perfectly know that knowledge is your ally in the IT World. In this article will discuss the Facroty and Intefrace concepts in a short way.
Interface
Simply, it is a definition of the abstract type that contains only operations without any data. When in a specific class all interface members are implemented into a body, confidently can say that class fylly inhertics an interface. Every class that implements an interfece can create different references of each member. In a nutshell it is a set of method or functions as a pattern and can be used many times.
Abstract Factory
Is a design pattern that has a target to deliver specific interfaces to create different objects of one type (the same family) without definition of specific classes. Allows one object to create different, related to each other, representation of subobjects defining their types during program work.
Conclusion
This design pattern gives us a clear view of program code and its subsequence usage. Below you can find simple solution of the above concepts in Kotlin.
import java.lang.IllegalArgumentException /* We have one interface that provides one operation (member) as a method. The "transform()" operation takes string as a parameter and returns string as a result. */ interface Operation { fun transform(initialString: String):String } /* This class inherits "Operation" interface and takes its one member. The only one purpose of this class is to transform initialString to upper case and return that string. */ class OperationToUpperCase():Operation { override fun transform(initialString: String): String { return initialString.toUpperCase() } } /* We have a similar situation as before. We took an interface and modified transform method. In this case, we have a situation of reversing the initial string. After that method simply returns the result. */ class OperationReverse():Operation { override fun transform(initialString: String): String { return initialString.reversed() } } /* More complicated example, but still based on the entrance concept. The transform method takes initial string and converts to lower case. After that takes every other char and makes it to upper case and then returns the result. If a program is requesting an operation that cannot be returned by Factory, the specific exception will be thrown. */ class OperationToUpperCaseEveryOtherChar():Operation { override fun transform(initialString: String): String { val lowerCaseString:String = initialString.toLowerCase() var result:String = "" for (position in 0..lowerCaseString.length - 1) { result += if (position % 2 == 0) { lowerCaseString[position].toUpperCase() } else { lowerCaseString[position] } } return result } } /* At least our Factory class that provides (returns) specific requested operation. Companion object allows us to invoke a method without creating an instance. */ class OperationFactory() { companion object { fun getOperation(type:String):Operation = when (type) { "upper" -> OperationToUpperCase() "reverse" -> OperationReverse() "upperEveryOtherChar" -> OperationToUpperCaseEveryOtherChar() else -> throw IllegalArgumentException("Operation not supported!") } } } /* Usage examples */ fun main(args:Array<String>) { lateinit var operation:Operation operation = OperationFactory.getOperation("upper") println(operation.transform("Cezary Kaszuba")) operation = OperationFactory.getOperation("reverse") println(operation.transform("Some Car Went on the Road")) operation = OperationFactory.getOperation("upperEveryOtherChar") println(operation.transform("The Sun is beautiful as well as the Moon.")) }