dimanche 17 juin 2018

Pattern where implementations register themselves in a object registry

I have several classes that implement an abstract class "Product". To follow the Open-Closed-Principle I would like the implementation classes in a way that they register themselves in a ProductRegistry singleton object. When adding new "Product" classes, it should be sufficient to write them or put them in the class path without having to touch the ProductRegistry class.

Below are my first steps but it seems that the objects are lazy-initialized. Can I change that? Or should I use a init-block in every subclass? (didn't like that approach as it's easy to forget).

 abstract class Product {
    val id : Int

    constructor(id : Int) {
        println("ctor with id=$id")
        this.id = id
        ProductRegistry.register(this)
    }
    abstract fun getColor(): String
 }

object BrownProduct : Product(2) {
    override fun getColor() = "brown"
}

object ProductRegistry {
    private val registry = HashSet<Product>()

    fun register(product: Product) {
        println("Registering: $product")
        registry.add( product)
    }

    fun fromId(id: Int): Product {
        return registry.filter { it.id == id }.first()
    }
}

Test:

class TestProdFac {
    @Test
    fun test1() {
        // println(RedProduct) <- if called before, then test works
        assertEquals(RedProduct::class, ProductRegistry.fromId(1)::class)
    }
}

Aucun commentaire:

Enregistrer un commentaire