Object-Oriented Programming/Design Pattern

Composite Pattern, 컴포지트 패턴

yongmin.Lee 2022. 7. 28. 12:13

Composite Pattern

  • 정의
    • 여러 개의 객체들로 구성된 복합 객체와 단일 객체를 클라이언트에서 구별 없이 다루게 해주는 패턴
    • 클라이언트는 전체와 부분을 구분하지 않고 동일한 인터페이스 를 사용
    • "일괄적인 관리"가 가능
  • 패턴구조
    • Component
      • Leaf 클래스와 전체에 해당하는 Composite 클래스의 공통 인터페이스
      • 클라이언트는 Component를 통해 composite내의 오브젝트들을 다룬다
    • Leaf
      • 부분 클래스
      • Component 인터페이스를 구현하며 Composite를 구성하는 요소
    • Composite
      • 전체 클래스
      • Component 인터페이스를 구현
      • 복수 개의 Component를 갖도록 정의함으로써 복수 개의 Leaf, 심지어 복수 개의 Composite 객체를 가질수 있다.

 

Composite Pattern 적용 예시

1. composite pattern 적용 전

class Computer {
    var keyboard : Keyboard?
    var body : ComputerBody?
    
    func setKeyBoard(keyboard : Keyboard) {
    	self.keyboard = keyboard
    }
    
    func setComputerBody(body: ComputerBody) {
    	self.body = body
    }
    
    func powerOn() {
    	self.keyboard?.powerOn()
        self.body?.powerOn()
    }
}

class Keyboard {
    func powerOn() {
    	print("Keyboard powerOn")
    }
}

class ComputerBody {
    func powerOn() {
    	print("ComputerBody powerOn")
    }
}
  • 새로운 부품을 추가할때마다 컴퓨터클래스에 수정사항이 많이 생긴다
    • 새로운 부품 클래스 멤버필드 생성
    • setter함수 추가
    • powerOn()과 같이 부품의 메소드를 컴퓨터의 해당 메소드에 추가
  • 부품의 수정사항이 생길때 마다 컴퓨터클래스에서 해당 부품의 수정사항을 반영해줘야 한다
  • 개방폐쇄원칙이 지켜지지 않고 있다

 

2. composite pattern 적용 후

protocol ComputerDevice {
    func powerOn()
}

class Computer: ComputerDevice {
    var devices: [ComputerDevice] = .init()
    
    func addDevice(device: ComputerDevice) {
    	self.devices.append(device)
    }
    
    func powerOn() {
    	self.devices.forEach { device in 
        	device.powerOn()
        }
    }
}

class KeyBoard: ComputerDevice {
    func powerOn() {
    	print("KeyBoard powerOn")
    }
}

class ComputerBody: ComputerDevice {
    func powerOn() {
    	print("ComputerBody powerOn")
    }
}
  • Component : ComputeDevice 객체
  • Leaf : KeyBoard, ComputerBody 객체
  • Composite : Computer 객체
  • Computer객체는 Leaf객체들을 그룹으로 묶어서 한번에 동작수행
  • 클라이언트는 Computer객체를 통해 부품 종류에 상관없이 부품을 추가할수 있고 일괄적 관리가 가능
  • Computer객체는 Leaf객체가 추가되어도 수정이 없다 => 개방폐쇄원칙 준수