[디자인 패턴] 커맨드 패턴, 팩토리 메서드 패턴, 상태 패턴
공부내용 공유하기

[디자인 패턴] 커맨드 패턴, 팩토리 메서드 패턴, 상태 패턴

커맨드 패턴

세 줄 개념

  • 실행 기능 단위로 캡슐화 함으로써 여러 기능을 실행할 수 있는 재사용성 높은 클래스 설계
  • 기능 자체를 캡슐화 하기 때문에 Invoker와 Reciver간의 의존성 자체를 제거(기능 자체의 세부구현 변경이 Invoker와 Reciver의 수정 없이 이뤄질 수 있음)
  • 기능 자체를 다루는 로직이 필요할 때 사용(되돌리기, 히스토리 기록 등)

유용한 사례

  • 실행 취소가 가능한 명령들을 다양하게 다뤄야 하는 텍스트 에디터
  • 보상 트랜잭션
  • 공유 리소스를 바탕으로 병렬 처리를 원할 때(ex. 커맨드 단위로 멀티 스레드에서 동작)

느낀 점

처음에 커맨드 패턴을 코드상에서 봤을 때 마치 side effect를 적극적으로 사용하는 패턴으로 보였음

excute()의 반환 타입이 실질적인 응답 데이터를 가지지 않는다는 점 + 매개변수를 넘기는 방식이 아니라는 점에서 그렇게 보았음

그러나 예제 코드를 자세히 보니 명령 자체를 캡슐화해서 그렇게 보이는 것 뿐이고, 매개변수 혹은 반환값에 대한 처리는 커맨드 객체 내부 구현 및 어플리케이션에서 커맨드를 바인딩 할 때 넘겨준다는 사실을 알았음

 

예시코드(refactoring.guru)

 

작성에 필요한 보일러 플레이트 코드가 있으며, 복잡성이 증가하는 단점은 있으나, 상기 커맨드 패턴이 유용한 사례에서 도입한다면 단점보다는 장점이 더 많은 좋은 패턴으로 보임

 

다만 각 커맨드의 인터페이스 설계를 잘 하지 않을 경우 커맨드 기능에 필요한 인터페이스 외에 너무 많은 컨텍스트의 정보를 들고 있게 될지도? (ex. 커맨드 호출 시점에 권한(로그인 여부)등의 확인이 필요하다면? 로그인 여부를 확인할 수 있는 기능을 커맨드 초기화시 주입해줘야함)

 

Command pattern

[Design Pattern] 커맨드 패턴이란 - Heee's Development Blog

커맨드 패턴

 

 

팩토리 메소드 패턴

팩토리 패턴과의 차이점

Simple Factory Pattern

단순히 인스턴스 생성 로직을 노출하지 않고 팩토리를 통해 객체 생성

SimpleFactory simpleFactory = new SimpleFactory();
IAnimal dog = simpleFactory.CreateDog(); // Create dog
IAnimal tiger = simpleFactory.CreateTiger(); // Create tiger

 

Factory Method Pattern

팩토리에 대한 인터페이스를 정의하고, 해당 인터페이스를 지킨 팩토리에서 어떤 인스턴스를 생성할지 결정(위임)

AnimalFactory dogFactory = new DogFactory(); 
IAnimal dog = dogFactory.CreateAnimal(); // Create dog

AnimalFactory tigerFactory = new TigerFactory();
IAnimal tiger = tigerFactory.CreateAnimal(); // Create tiger

 

조금 다른 예시

Simple Factory Pattern

 

Factory Method Pattern

Nokia Factory에 현재 클라이언트에서 사용하지 않는(호출되지 않는) 메소드가 추가될 경우

class NokiaFactory {
    // old code
    public void Foo() { ... }
}

Simple Factory Pattern에서는 MobileFactory 구현과 클라이언트에 영향을 주지 않고 구현할 수 없음

Factory Method Pattern에서는 NokiaFactory 구현만 바꾸면 클라이언트는 변경사항을 몰라도 됨

 

Simple factory vs Factory method

Design Patterns: Factory vs Factory method vs Abstract Factory

 

상태 패턴

세 줄 개념

  • 객체의 현재 (유한)상태에 따라 동작을 제한하여 복잡성을 낮추는 것
  • 전이(transition)를 통해 상태간의 변경을 일으킴
  • 유한 상태 기계(finite state machine)의 개념에 가까움

유용한 사례

  • 명확하게 상태별로 가능한 action들이 나눠진 경우 각 상태별 관심사 분리
  • 조건문과 분기처리가 많은 복잡한 로직 단순화
  • 컨텍스트의 상태 폭발 제어

XState

XState로 js+ts 진영에서 간단하게 상태 패턴 사용 가능

createMachine({
  initial: "waiting",
  states: {
    "waiting": {
      on: {
        "leave home": "on a walk",
      },
    },
    "on a walk": {
      initial: "walking",
      states: {
        walking: {
          on: {
            "speed up": "running",
          },
        },
        running: {
          on: {
            "slow down": "walking",
          },
        },
      },
      on: {
        "arrive home": "walk complete",
      },
    },
    "walk complete": {
      type: "final",
    },
  });

What are state machines and statecharts? | Stately Docs

State pattern

상태 패턴