Personal-Study/Design Patterns

[TS Design Patterns] 행동 패턴 - 상태

Aaron-Kim 2023. 11. 12. 12:21

State

- 객체의 내부 상태가 변경될 때 해당 객체가 그의 행동을 변경할 수 있도록 함

- 객체가 행동을 변경할 때 객체가 클래스를 변경한 것처럼 보일 수 있음

- 상태 관련 행동들을 별도의 상태 클래스들로 추출하여 원래 객체가 자체적으로 작동하는 대신

   상태 클래스들에 작업을 위임하도록 강제함

- TS에서 대규모 switch 기반 상태 머신들을 객체들로 변환하는데 사용

 

- 예시

/**
 * The Context defines the interface of interest to clients. It also maintains a
 * reference to an instance of a State subclass, which represents the current
 * state of the Context.
 */
class Context {
  /**
   * @type {State} A reference to the current state of the Context.
   */
  //@ts-ignore
  private state: State;

  constructor(state: State) {
    this.transitionTo(state);
  }

  /**
   * The Context allows changing the State object at runtime.
   */
  public transitionTo(state: State): void {
    console.log(`Context: Transition to ${(<any>state).constructor.name}.`);
    this.state = state;
    this.state.setContext(this);
  }

  /**
   * The Context delegates part of its behavior to the current State object.
   */
  public request1(): void {
    this.state.handle1();
  }

  public request2(): void {
    this.state.handle2();
  }
}

/**
 * The base State class declares methods that all Concrete State should
 * implement and also provides a backreference to the Context object, associated
 * with the State. This backreference can be used by States to transition the
 * Context to another State.
 */
abstract class State {
  //@ts-ignore
  protected context: Context;

  public setContext(context: Context) {
    this.context = context;
  }

  public abstract handle1(): void;

  public abstract handle2(): void;
}

/**
 * Concrete States implement various behaviors, associated with a state of the
 * Context.
 */
class ConcreteStateA extends State {
  public handle1(): void {
    console.log('ConcreteStateA handles request1.');
    console.log('ConcreteStateA wants to change the state of the context.');
    this.context.transitionTo(new ConcreteStateB());
  }

  public handle2(): void {
    console.log('ConcreteStateA handles request2.');
  }
}

class ConcreteStateB extends State {
  public handle1(): void {
    console.log('ConcreteStateB handles request1.');
  }

  public handle2(): void {
    console.log('ConcreteStateB handles request2.');
    console.log('ConcreteStateB wants to change the state of the context.');
    this.context.transitionTo(new ConcreteStateA());
  }
}

/**
 * The client code.
 */
const context = new Context(new ConcreteStateA());
context.request1();
context.request2();

 

- 활용


[아티클]

[TS 사용 예시]

반응형