오늘도 더 나은 코드를 작성하였습니까?

Abstract Factory Pattern 추상 팩토리 패턴 (feat. kotlin) 본문

디자인패턴/생성패턴

Abstract Factory Pattern 추상 팩토리 패턴 (feat. kotlin)

hik14 2024. 6. 4. 18:39

정의

소프트웨어 엔지니어링에서 Abstract Factory Pattern(추상 팩토리 패턴)은 Concreate Class(구체적인 클래스)를 지정하지 않고 공통 테마를 갖는 개별 팩토리 그룹을 캡슐화하여 관련 객체의 패밀리(제품군)를 생성하는 방법을 제공하는 디자인 패턴입니다.

 

클라이언트(객체를 사용하는 곳)에서,  Abstract Factory Class를 상속하는 Concreate Class의 객체를 생성한 후, 팩토리의 일반 인터페이스를 사용하여 객체의 패밀리에 속하는 구체적인 객체를 생성하여 준다. 클라이언트는 해당 팩토리의 일반 인터페이스만 사용하기 때문에 각 내부 팩토리로 부터 어떻게 구체적인 객체를 생성해 주는지 알 수 없습니다.

 

Abstract Factory Pattern(추상 팩토리 패턴)은 객체의 패밀리(제품군) 실제 구현의 세부 사항을 일반 인터페이스를 사용하여 분리하고 object composition(인터페이스 구현)을 사용합니다. 객체 생성은 팩토리 인터페이스에 공개된 메서드를 통해서만 가능합니다.

구현

아래와 같이 Factory Method Pattern을 이용하여 구현된 Gpu를 생성하는 코드가 있다고 가정을 해보자!

어느날, 각 회사별로 CPU를 생산하기로 했다. 

그렇다면, 아래와 같이 코드를 수정할 수 있을 것이다.

 

하지만 이렇게 되면 추후에 CPU 말고 또 다른 부품이 추가된다면, 지속적으로 각 각의 Factory Class들의 createComponent는 Type의 증가에 맞춰서 수정되어야 하며, 이것은 SOLDE 원칙중 Open-Closed 원칙을 위배하고 있다. 이렇게 각 개별 팩토리 그룹을 캡슐화하여 관련 객체의 패밀리(제품군) 여기선 (CPU, GPU,...등등)를 생성을 효과적으로 구현할 수있도록 도와주는것이 추상 팩토리 패턴이다.

 

Creators

abstract class Company {
    fun assembleCPU(): CPU {
        val cpu = createCPU()
        cpu.assembleCPU()
        return cpu
    }

    protected abstract fun createCPU(): CPU

    fun assembleGPU(): GPU {
        val gpu = createGPU()
        gpu.assembleGPU()
        return gpu
    }

    protected abstract fun createGPU(): GPU
}
class AmdManufacturer : Company() {
    override fun createCPU(): CPU = AmdCpu()

    override fun createGPU(): GPU = AmdGpu()
}
class NvidiaManufacturer : Company() {
    override fun createCPU(): CPU = NvidiaCpu()

    override fun createGPU(): GPU = NvidiaGpu()
}

 

 

Family of Product

interface CPU {
    fun assembleCPU()
}

class NvidiaCpu : CPU {
    override fun assembleCPU() {
        // business logic relevant to Amd
        println("nvidiaCpu assembled")
    }
}

class AmdCpu : CPU {
    override fun assembleCPU() {
        // business logic relevant to Amd
        println("amdCpu assembled")
    }
}
interface GPU {
    fun assembleGPU()
}

class NvidiaGpu : GPU {
    override fun assembleGPU() {
        // business logic relevant to Amd
        println("nvidiaGpu assembled")
    }
}

class AmdGpu : GPU {
    override fun assembleGPU() {
        // business logic relevant to Amd
        println("amdGpu assembled")
    }
}

 

장점

- 연관된 객체(제품군)을  다양하게 할 필요성이 있을 때 매우 유용하다.

- Factory Method Pattern -> Abstract Factory로 확장해 나갈 수 있다.

- 제품군을 추가시 Open-Closed / Single Responsibility 원칙을 잘 준수한다.

- 연관된 코드를 한 곳에 모아 관리하기 쉽다.