반응형
State pattern 이란
객체가 상태에 따라 같은 메소드가 다른 행위를 하도록 위임하는 디자인 패턴이다. 공통 메소드의 인터페이스를 통해, 각 상태는 클래스로 분리시켜 표현한다.
State pattern 적용
아래 예는 스타크래프트의 시즈탱크의 시즈모드 활성화, 비활성화를 State 패턴을 적용해본 것이다.
시즈탱크의 시즈모드는 멱등성을 가진다. 즉, 시즈탱크는 시즈모드가 활성화 됐을 때 시즈모드를 할 수 없고 시즈모드 비활성화만 할 수 있다. 반대로 비활성화 된 경우 시즈모드 활성화를 할 수 있지만 비활성화는 할 수 없다. 이런 구현을 state 패턴으로 할 수 있다. 또한 같은 공격(attack) 메소드라 할지라도 시즈모드 활성화, 비활성화 상태에 따라 공격하는 방식이 다른데 이런 구현도 가능하다.
interface State {
enableSizeMode(sizeTank: SizeTank): void;
disableSizeMode(sizeTank: SizeTank): void;
attack(): void;
}
class OnSizeMode implements State {
enableSizeMode(sizeTank: SizeTank): void {
console.log('시즈모드를 활성화 할 수 없다.');
}
disableSizeMode(sizeTank: SizeTank): void {
console.log('시즈모드 비활성화!');
sizeTank.setState(new OffSizeMode());
}
attack(): void {
console.log('대포 발사');
}
}
class OffSizeMode implements State {
enableSizeMode(sizeTank: SizeTank): void {
console.log('시즈모드 활성화!');
sizeTank.setState(new OnSizeMode());
}
disableSizeMode(sizeTank: SizeTank): void {
console.log('시즈모드 비활성를 할 수 없다');
}
attack(): void {
console.log('퉁퉁포 발사');
}
}
class SizeTank {
constructor(private state: State = new OffSizeMode()) {}
setState(state: State) {
this.state = state;
}
activeSizeMode() {
this.state.enableSizeMode(this);
}
inActiveSizeMode() {
this.state.disableSizeMode(this);
}
attack() {
this.state.attack();
}
}
function Main() {
const sizeTank = new SizeTank();
sizeTank.attack(); // 퉁퉁포 발사
sizeTank.activeSizeMode(); // 시즈모드 활성화!
sizeTank.activeSizeMode(); // 시즈모드를 활성화 할 수 없다.
sizeTank.attack(); // 대포 발사
sizeTank.attack(); // 대포 발사
sizeTank.inActiveSizeMode(); // 시즈모드 비활성화!
sizeTank.inActiveSizeMode(); // 시즈모드 비활성를 할 수 없다
}
Main();
결론
비즈니스 로직을 구현할 때 상태를 갖는 객체는 상태에 따라 같은 메소드라 할지라도 다르게 동작해야 할 경우가 있다. 예를 들어, 쇼핑몰에서 "주문 배송지 변경" 이라는 비즈니스 로직은 주문의 상태가 "배송 전' 일 때 가능하지 "배송 후"에는 불가능해야 한다. 이와 비슷한 경우 State pattern 패턴을 적용하면 될 것 같다.
반응형
'Design Pattern' 카테고리의 다른 글
Observer pattern, 옵저버 패턴 (0) | 2020.05.18 |
---|---|
Command Pattern, 커맨트 패턴 (0) | 2020.04.13 |
Singleton pattern, 싱글톤 패턴 (0) | 2020.04.02 |
Strategy pattern, 스트레이티지 패턴 (0) | 2020.04.01 |