Don't give up!

[Design Pattern] 상태 패턴 (State Pattern) 본문

개발서적/Head First Design Patterns

[Design Pattern] 상태 패턴 (State Pattern)

Heang Lee 2021. 12. 24. 14:24
이 글은 에릭 프리먼의 'Head First Design Patterns'를 읽고 TIL(Today I Learned)로써 정리한 내용을 기록하는 글입니다.
자세한 내용은 책을 통해 확인하실 수 있습니다.

알라딘: Head First Design Patterns (aladin.co.kr)

 

Head First Design Patterns

볼 거리가 많고 재미있으면서도, 머리 속에 쏙쏙 들어오는 방식으로 구성된 Head First 시리즈. 패턴의 근간이 되는 객체지향 디자인 원칙, 중요한 패턴, 디자인 적용 방법, 쓰지 말아야 하는 이유

www.aladin.co.kr

상태 패턴 (State Pattern)

상태 패턴은 객체의 내부 상태가 바뀜에 따라 객체의 행동을 바꿀 수 있는 디자인 패턴입니다.

각 상태마다 클래스를 분리하여 정의하고, 구성 관계를 통해 여러 상태 객체를 바꿔가면서 사용함으로써 클라이언트는 Context의 메소드를 호출하는 것 만으로도 상태 관련 작업을 처리할 수 있습니다.

//State 인터페이스
public interface State {
    public void insertQuarter();
    public void ejectQuarter();
    public void turnCrank();
    public void dispense();
}

//Context 클래스
public class GumballMachine {
    State soldOutState;
    State noQuarterState;
    State hasQuarterState;
    State soldState;
    
    State state = soldoutState;
    int count = 0;
    
    public GumballMachine(int numberGumballs) {
        soldOutState = new SoldOutState(this);
        noQuarterState = new NoQuarterState(this);
        hasQuarterState = new HasQuarterState(this);
        soldState = new SoldState(this);
        this.count = numberGumballs;
        if (numberGumballs > 0) {
            state = noQuarterState;
        }
    }
    
    public void insertQuarter() {
        state.insertQuarter();
    }
    
    public void ejectQuarter() {
        state.ejectQuarter();
    }
    
    public void turnCrank() {
        state.turnCrank();
        state.dispense();
    }
    
    void setState(State state) {
        this.state = state;
    }
    
    void releaseBall() {
        System.out.println("A gumball comes rolling out the slot...");
        if (count != 0) {
            count = count - 1;
        }
    }
}

//ConcreteState 클래스들
public class HasQuaterState implements State {
    GumballMachine gumballMachine;
    
    public HasQuaterState(GumballMachine gumballMachine) {
        this.gumballMachine = gumballMachine;
    }
    
    public void insertQuarter() {
        System.out.println("동전은 한 개만 넣어주세요.");
    }
    
    public void ejectQuarter() {
        System.out.println("동전이 반환됩니다.");
        gumballMachine.setState(gumballMachine.getNoQuarterState());
    }
    
    public void turnCrank() {
        System.out.println("손잡이를 돌리셨습니다.");
        gumballMachine.setState(gumballMachine.getSoldState());
    }
    
    public void dispense() {
        System.out.println("알맹이가 나갈 수 없습니다.");
    }
}

public class SoldState implements State {
    public void insertQuarter() {
        System.out.println("잠깐만 기다려 주세요. 알맹이가 나가고 있습니다.");
    }
    
    public void ejectQuarter() {
        System.out.println("이미 알맹이를 뽑으셨습니다.");
    }
    
    public void turnCrank() {
        System.out.println("손잡이는 한 번만 돌려주세요.");
    }
    
    public void dispense() {
        gumballMachine.releaseBall();
        if(gumballMachine.getCount() > 0) {
            gumballMachine.setState(gumballMachine.getNoQuarterState());
        } else {
            System.out.println("out of gumballs!");
            gumballMachine.setState(gumballMachine.getSoldOutState());
        }
    }
}
....