본문 바로가기
🧩Design Patterns

[Design Patterns]Factory pattern, 객체를 만들어내는

by 빈성_ 2022. 7. 4.
반응형

Intro

이번에는 Factory pattern입니다. Factory pattern은 공장에서 상품을 찍어내는 것처럼 객체를 찍어내는 패턴입니다. Factory pattern은 factory Method와 abstract Factory, 두 가지로 나뉩니다. 공부하면서 비슷하지만 다른 두 형태를 구분하기가 까다로웠는데 stackoverflow의 답변 하나가 나름(?) 명쾌하게 풀어줍니다.

The main difference between a "factory method" and an "abstract factory" is that the factory method is a method, and an abstract factory is an object.

‘factory method는 method이고, abstract factory는 object다.’ 어찌 보면 말장난처럼 보이기도 합니다만 이 문장만큼 두 유형의 차이를 단순 명료하게 얘기해주는 것도 없을 것 같다는 생각입니다.

Factory Method

위에서 말했듯이 factory method는 method입니다. method가 객체를 return하는 모습이죠. 그 모습을 컴퓨터에 빗대서 하나 만들어봤습니다.

class TypeComputerFactory: ComputerFactory {

    override fun createComputer(type: String): Computer? {
        return when (type) {
            "laptop" -> LaptopComputer()
            "desktop" -> DesktopComputer()
            else -> null
        }
    }
}

ComputerFactory는 type을 입력받아 그에 맞는 Computer 객체를 return하고 있습니다. 이 모습이 아주 단순한 factory method의 모습입니다. 어느 블로그에서는 이렇게 간단한 factory method는 ‘자주 쓰이는 관용구에 가깝다’라고 표현합니다.

factory method를 사용하게 되면 사용자(client)와 구상 클래스(concrete class)의 결합도가 낮아지게 됩니다. client는 어떤 concrete class가 return 되는지 신경 쓰지 않아도 되고, concrete class를 제공하는 입장에서도 client가 어떤 concrete class를 사용할지 신경 쓰지 않아도 되기 때문이죠.

Abstract Factory

abstract factory는 object입니다. factory method는 concrete class를 만들기 위한 method가 주어졌고, abstract factory는 concrete class를 만들기 위한 object가 주어집니다.

// GamingComputerFactory.kt
class GamingComputerFactory: ComputerFactory {

    override fun CPU(): CPU {
        return HighPerformanceCPU()
    }

    override fun GPU(): GPU {
        return HighPerformanceGPU()
    }

    override fun Storage(): Storage {
        return SSD()
    }
}

// OfficeComputerFactory.kt
class OfficeComputerFactory: ComputerFactory {

    override fun CPU(): CPU {
        return CostPerformanceCPU()
    }

    override fun GPU(): GPU {
        return CostPerformanceGPU()
    }

    override fun Storage(): Storage {
        return HDD()
    }
}

abstract factory의 모습은 이런 식입니다. factory method는 완성된 객체를 return하지만 abstract factory는 이를테면 부품(혹은 재료)을 세트로 가지고 있는 object를 제공하는 것이죠.

// Main.kt
val gamingComputerFactory = GamingComputerFactory()
val myComputer = MyComputer(gamingComputerFactory)
println(myComputer.use())
// MyComputer.kt
class MyComputer(computerFactory: ComputerFactory): Computer(computerFactory) {

    override fun use(): String {
        return "MyComputer CPU: ${computerFactory.CPU().info()}, GPU: ${computerFactory.GPU().info()}, Storage: ${computerFactory.Storage().info()}"
    }
}

이렇게 부품을 가지고 있는 factory object를 이용해서 원하는 곳에, 원하는 방법으로 사용하면 결과적으로는 factory method와 마찬가지로 객체가 생성됩니다.

abstract factory는 일련의 제품들을 생성하기에 좋습니다. 예를 들면 이런 식입니다.

class HighCPUComputerFactory: ComputerFactory {

    override fun CPU(): CPU {
        return HighPerformanceCPU()
    }

    override fun GPU(): GPU {
        return CostPerformanceGPU()
    }

    override fun Storage(): Storage {
        return HDD()
    }
}

비슷하지만 다른 제품들을 추가로 만들어내기에 좋은 패턴이죠.

Abstract Factory Pattern in Kotlin

Kotlin에서는 abstract factory pattern을 이렇게도 구현할 수 있다고 Baeldung에서 알려주는 방법입니다.

abstract class ComputerFactory {

    abstract fun createComputer(): Computer
}
class PersonalComputer: Computer {

    companion object Factory: ComputerFactory() {
        override fun createComputer(): Computer = PersonalComputer()
    }

    override fun check(): String {
        return "is PersonalComputer"
    }
}
val personalComputerFactory: ComputerFactory = PersonalComputer.Factory
val personalComputer: Computer = personalComputerFactory.createComputer()
println(personalComputer.check())

보시면 보시면 PersonalComputer class의 모습이 조금 다릅니다. concrete class와 factory object가 하나의 class에 뭉쳐있는 모습이죠. 코드가 길어지지 않는다면 이렇게 하나의 class만 관리해도 되는 것이 장점이 될 수도 있겠다는 생각을 해봅니다.

주저리주저리

factory method와 abstract factory, 비슷하지만 다른 두 녀석을 구분하려고 하니 꽤나 긴 시간이 걸렸네요. factory pattern을 알아가면서 의존성 역전 원칙(DIP, Dependency Inversion Principle)도 다시 한번 보게 되었습니다. 역시 객체 지향을 자유롭게 다루는 건 어렵네요. 그래도 조금씩 나아지고 있다는 느낌은 있습니다.

 

전체 소스 코드는 이곳에서 확인 가능하십니다.

반응형

'🧩Design Patterns' 카테고리의 다른 글

[Design Patterns]Observer pattern, 변화에 반응  (0) 2022.05.16

댓글