Gof의 디자인 패턴 - 명령 패턴

Groot·2024년 3월 17일
0

TIL

목록 보기
146/153
post-thumbnail
post-custom-banner

명령 패턴

  • 요청 자체를 캡슐화, 요청이 서로 다른 사용자를 매개변수로 만들고, 요청 대기, 로깅, 되돌릴 수 있는 연산 지원
  • 연산을 호출하는 객체와 수행하는 객체의 분리

활용성

  • 수행할 동작을 객체로 매개변수화 할 때
  • 서로 다른 시간에 요청을 명시하고, 저장, 실행하고 싶을 때
  • 실행 취소 기능을 지원할 때
  • 시스템이 고장 났을 때 재적용이 가능하도록 변경 과정에 대한 로깅을 지원하고 싶을 때
  • 기본적인 연산의 조합으로 만든 상위 수준 연산을 써서 시스템을 구조화 할 때

구조

요소

  • Command
    • 연산 수행에 필요한 인터페이스 선언
  • ConcreteCommand
    • Receiver 객체와 액션 간의 연결성 정의
    • 처리 객체에 정의된 연산을 호출하도록 Execute() 구현
  • Client
    • ConcreteCommand 객체를 생성하고 처리 객체로 정의
  • Invoker
    • 명령어에 처리를 수행할 것을 요청
  • Receiver
    • 요청에 관련된 연산 수행 방법을 알고 있다.

협력 방법

  • 사용자는 ConcreteCommand 객체를 생성하고 이를 Receiver로 지정
  • Invoker는 ConcreteCommand 객체를 저장
  • Invoker는 Command에 정의된 Execute() 호출
  • ConcreteCommand 객체는 요청을 실제 처리할 객체에 정의된 연산 호출

장점

  • Command는 연산을 호출하는 객체와 연산 수행 방법을 구현하는 객체를 분리할 수 있다.
  • 명령을 여러 개 복합한 복합 명령을 만들 수 있다.
  • 새로운 Command 객체를 추가하기 쉽다.
  • 작업들의 지연된 실행을 구현할 수 있다.

단점

  • 발송자와 수신자 사이에 완전히 새로운 레이어를 도입하기 때문에 코드가 더 복잡해질 수 있다.

예시 코드

// Command 프로토콜
protocol Command {
    func execute()
}

// Receiver
class DrawingReceiver {
    func drawCircle() {
        print("원 그려짐")
    }
    
    func drawRectangle() {
        print("사각형 그려짐")
    }
}

// 원을 그리는 ConcreteCommand
class DrawCircleCommand: Command {
    private var receiver: DrawingReceiver
    
    init(receiver: DrawingReceiver) {
        self.receiver = receiver
    }
    
    func execute() {
        receiver.drawCircle()
    }
}

// 사각형을 그리는 ConcreteCommand
class DrawRectangleCommand: Command {
    private var receiver: DrawingReceiver
    
    init(receiver: DrawingReceiver) {
        self.receiver = receiver
    }
    
    func execute() {
        receiver.drawRectangle()
    }
}

// Invoker
class DrawingInvoker {
    private var commands = [Command]()
    
    func addCommand(command: Command) {
        commands.append(command)
    }
    
    func executeCommands() {
        for command in commands {
            command.execute()
        }
        commands.removeAll()
    }
}

// Client
let drawingReceiver = DrawingReceiver()
let drawingInvoker = DrawingInvoker()

let drawCircleCommand = DrawCircleCommand(receiver: drawingReceiver)
let drawRectangleCommand = DrawRectangleCommand(receiver: drawingReceiver)

drawingInvoker.addCommand(command: drawCircleCommand)
drawingInvoker.addCommand(command: drawCircleCommand)
drawingInvoker.executeCommands()

drawingInvoker.addCommand(command: drawRectangleCommand)
drawingInvoker.executeCommands()

참고

profile
I Am Groot
post-custom-banner

0개의 댓글