상태(State) 패턴

차동준·2022년 7월 27일
0

CS-디자인패턴

목록 보기
14/16
post-thumbnail

👨‍💻 상태 패턴이란?


객체의 상태가 바뀜에 따라서 상태를 정의한 클래스의 메소드를 통해
객체의 행동과 상태를 바꿀 수 있는 디자인 패턴


예시) 자동차의 상태

pulic interface CarState {
	public void startButton(); // 시동 버튼 누르기
	public void accel(); // 엑셀 밟기
    public void breaking(); // 정지
}

상태패턴의 예시를 자동차의 각 상태에 따른 메소드 들의 변화를 통해 설명하려고 할 때
자동차의 상태에 따른 행동들에 대해 캡슐화한 인터페이스가 위와 같다.


예시) 시동꺼짐상태, P(arking), D(rive), R(ear) 상태

public class OffState implements CarState {
	Car car;
    
    public OffState(Car car) {
    	this.car = car;
    }
    
	public void startButton() {
    	System.out.println("시동을 켭니다");
        this.car.setState(this.car.Parking);
    }
    
	public void accel() {
    	System.out.println("시동 꺼짐 상태에서는 엑셀이 작동하지 않습니다");
    }
    
    public void breaking() {
    	System.out.println("브레이크가 작동합니다");
    }
}

시동 꺼짐 상태에 대한 상태 클래스 구현

public class Parking implements CarState {
	Car car;
    
    public Parking(Car car) {
    	this.car = car;
    }
    
    public void startButton() {
    	System.out.println("시동을 끕니다");
        this.car.setState(this.car.OffState);
    }
    
    public void accel() {
    	System.out.println("주차브레이크 모드 중 차가 앞으로 나가지 않습니다.");
    }
    
    public void breaking() {
    	System.out.println("브레이크가 작동합니다");
    }
}

Parking(주차) 상태에 대한 상태 클래스 구현

public class Drive implements CarState {
	Car car;
    
    public Drive(Car car) {
    	this.car = car;
    }
    
    public void startButton() {
    	System.out.println("주행 중에는 시동을 끌 수 없습니다");
    }
    
    public void accel() {
    	System.out.println("전진 가속 합니다");
	}
    
    public void breaking() {
    	System.out.println("브레이크를 밟아 속도를 줄입니다");
    }
}

Drive(주행) 상태에 대한 상태 클래스 구현

public class Rear implements CarState {
	Car car;
    
    public Rear(Car car) {
    	this.car = car;
    }
    
    public void startButton() {
    	System.out.println("후진 중에는 시동을 끌 수 없습니다");
    }
    
    public void accel() {
    	System.out.println("후진 가속 합니다");
    }
    
    public void breaking() {
    	System.out.println("브레이크를 밟아 속도를 줄입니다");
    }
}

Rear(후진주행) 상태에 대한 상태 클래스 구현

위와 같이 자동차는 4개의 상태에 따라서 엑셀을 밟거나 브레이크를 밟거나
스타트버튼을 눌렀을 때 동작하는 경우가 다르다.

이제 이 상태들을 가지고 Car 클래스를 구현해보면

예시) 상태를 적용한 Car 클래스 구현

public class Car {
	CarState OffState;
    CarState Parking;
    CarState Drive;
    CarState Rear;
    
    CarState state;
    
    public Car() {
    	this.offState = new OffState(this);
        this.Parking = new Parking(this);
        this.Drive = new Drive(this);
        this.Rear = new Rear(this);
        
        this.state = this.offState;
    }
    
    public void startButton() {
    	this.state.startButton();
    }
    
    public void accel() {
    	this.state.accel();
    }
    
    public void breaking() {
    	this.state.breaking();
    }
}

이렇게 상태 클래스에 행위를 위임하면서 동작과 그에 따른 상태를 변경할 수 있는 것이 상태패턴이다.
(최대한 간단하게 예시를 들기 위해서 간단한 동작들만 구현하였음.)



🔎 상태패턴의 장단점


장점

  1. 동작의 추가 수정 및 유지보수가 용이하다.

단점

  1. 상태가 많아질 경우 관리해야 할 클래스가 많아진다.



🔎 상태패턴 vs 전략패턴


메소드 동작을 캡슐화한 인터페이스를 구현한 클래스에게
행위를 위임시키는 방법은 전략패턴에서도 확인할 수 있었다.

그렇다면 이 둘의 차이점은 과연 무엇일까?

상태패턴은 상태 변화에 외부 개입이 필요가 없다.
전략패턴은 상태 변화에 외부 개입이 필요하다.
상태패턴은 스스로 State를 바꿀 수 있지만, 전략패턴은 사용자의 입력이 필요하다.

상태패턴은 위 예시에서 OffState 클래스와 Parking에서의 startButton() 메소드를 보면 상태클래스 안에서 자동적으로 상태를 변화시켜주는 것을 확인할 수 있다.

하지만 전략패턴에서는 클라이언트에서 어떤 전략클래스를 사용할지를 정해주어야 한다.

profile
백엔드를 사랑하는 초보 개발자

0개의 댓글