Abstract Factory pattern

2019. 11. 12. 22:46Backend

Wikipedia 는 Abstract factory pattern 에 대해 이렇게 이야기하고있다.

The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes. 

즉 factories 를 grouping 하는 pattern 이라 할 수 있겠다.

 

In normal usage, the client software creates a concrete implementation of the abstract factory and then uses the generic interface of the factory to create the concrete objects that are part of the theme. The client doesn't know (or care) which concrete objects it gets from each of these internal factories, since it uses only the generic interfaces of their products. This pattern separates the details of implementation of a set of objects from their general usage and relies on object composition, as object creation is implemented in methods exposed in the factory interface.

 

wikipedia 를 바탕으로 코틀린 코드를 작성해보았다.

fun main(arguments: Array<String>) {
    // This is just for the sake of testing this program,
    // and doesn't have to do with the Abstract Factory pattern.
    val randomAppearance = listOf("osx", "win").get(Random().nextInt(2))

    // get the button factory for an appearance
    val factory = AbstractFactory.factory(randomAppearance)

    // use the factory to create the button
    val button = factory.createButton()
    button.paint()
}

상황은 이러하다. 운영체제에 따라 다른 GUI 들이 있고, GUI 에 따라 다른 Button 들이 존재할 것이다.(즉 OSX GUI 에 Window Button 이 들어갈 일은 없다고 가정한다)

이를 이해하고 먼저 Client 코드를 보자. 클라이언트는 운영체제 명으로 팩토리를 생성하고 생성된 팩토리를 통해 버튼을 생성한다.

클라이언트 코드 내에서는 이게 어떤 버튼 클래스를 참조하는지 어떤 Gui Interface 를 이용하는건지 전혀 알 수 없다. 펙토리 내에 은닉되어 있다.

class AbstractFactory {
    interface GUIFactory {
        fun createButton(): Button
    }

    private class WinGuiFactory : GUIFactory {
        override fun createButton(): Button = WinButton()
    }

    private class OSXGuiFactory : GUIFactory {
        override fun createButton(): Button = OsXButton()
    }

    companion object {
        fun factory(appearance: String) =
            when (appearance) {
                "osx" -> OSXGuiFactory()
                "win" -> WinGuiFactory()
                else -> throw IllegalStateException()
            }


    }
}

은닉한 GuiFactory 이다. GuiFactory interface 가 존재하고 각 GuiFactory 마다 상응하는 운영체제에 따른 버튼을 생성하고 있다.

interface Button {
    fun paint()
}

class WinButton: Button {
    override fun paint() {
        println("winButton")
    }

}
class OsXButton: Button {
    override fun paint() {
        println("OsXButton")
    }

}

 

'Backend' 카테고리의 다른 글

Code review (Worklog)  (0) 2020.04.09
Apache Avro  (0) 2019.11.13
State pattern VS strategy pattern, what is the difference?  (0) 2019.11.10
Logger, Log4J? Slf4j?  (0) 2019.11.10
Retrofit, what is better?  (0) 2019.10.29