Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import kotlin.reflect.KClass
- import kotlinx.coroutines.*
- fun main() {
- println("Welcome to Thingville, population 1")
- val factory = ThingFactory(Thing1::class)
- factory?.run() // "Run Fast!"
- factory?.play() // "Run Hard!"
- val factory2 = ThingFactory(Thing2::class) // Run Time Error: Already created as type: class Thing1
- val factory3 = ThingFactory(NoThing::class) // Compile Time Error: None of the following functions can be called with the arguments supplied: public constructor ThingFactory(clazz: ThingFactory.ThingType) defined in ThingFactory public inline fun <reified T : SomeThing> ThingFactory(clazz: KClass<???>): ThingFactory?
- // Thread safe check
- runBlocking {
- val deferred = (1..20).map { n ->
- GlobalScope.async {
- val r = (1..10).random()
- println("In ${n}")
- try {
- when {
- r % 2 == 0 -> {
- println("Create ${n} Thing1")
- ThingFactory(Thing1::class)
- }
- else -> {
- println("Create ${n} Thing2")
- ThingFactory(Thing2::class)
- }
- }
- } catch(e: RuntimeException) {
- println("Error ${n} : ${e.message}")
- }
- println("Out ${n}")
- }
- }
- deferred.awaitAll()
- }
- }
- sealed class SomeThing {
- abstract fun run()
- abstract fun play()
- }
- class Thing1: SomeThing() {
- override fun run() = println("Run Fast!")
- override fun play() = println("Play Hard!")
- }
- class Thing2: SomeThing() {
- override fun run() = println("Run Silly!")
- override fun play() = println("Play Soft!")
- }
- class NoThing {}
- interface ClassBackedEnum {
- fun toClass(): Any
- }
- inline fun <reified T: SomeThing> ThingFactory(clazz: KClass<T>): ThingFactory? =
- when(clazz) {
- Thing1::class -> ThingFactory(ThingFactory.ThingType.Thing1Type)
- Thing2::class -> ThingFactory(ThingFactory.ThingType.Thing2Type)
- else -> throw RuntimeException("Unknown type: $clazz")
- }
- class ThingFactory private constructor() {
- enum class ThingType(): ClassBackedEnum {
- Thing1Type {
- override fun toClass() = Thing1::class
- },
- Thing2Type {
- override fun toClass() = Thing2::class
- }
- }
- constructor (clazz: ThingType): this() {
- if (myThing == null) {
- when(clazz.toClass()) {
- Thing1::class -> myThing = Thing1()
- Thing2::class -> myThing = Thing2()
- }
- } else {
- if (myThing?.javaClass?.kotlin != clazz.toClass()) {
- throw RuntimeException("Already created as type:${myThing?.javaClass?.kotlin}")
- }
- }
- }
- fun run() {
- myThing?.run()?: throw RuntimeException("Singleton not instantiated")
- }
- fun play() {
- myThing?.play()?: throw RuntimeException("Singleton not instantiated")
- }
- companion object {
- @Volatile var myThing: SomeThing? = null
- @Synchronized set(value: SomeThing?) {
- val i = myThing
- if (i != null) {
- field = i
- } else {
- field = value
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement