상태 패턴
Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 98번째.
상태 패턴(State pattern)은 객체의 내부 상태가 변경될 때 객체가 행동을 변경할 수 있도록 허용하여, 마치 객체의 클래스가 바뀐 것처럼 보이게 합니다. 여러 상태를 처리하기 위해 복잡한 조건문을 사용하는 대신, 각 상태를 별도의 클래스로 캡슐화하고 현재 상태 객체에 행동을 위임합니다.
이 패턴은 현재 상태에 대한 참조를 유지하는 Context와 가능한 각 상태에 대한 동작을 정의하는 State 클래스들로 구성됩니다. 컨텍스트의 상태가 변경되면 그 동작도 자동으로 변경됩니다:
abstract class DocumentState {
void publish(Document doc);
String getStatus();
}
class DraftState implements DocumentState {
@override
void publish(Document doc) {
print('Moving to review...');
doc.setState(ReviewState());
}
@override
String getStatus() => 'Draft';
}
class ReviewState implements DocumentState {
@override
void publish(Document doc) {
print('Document published!');
doc.setState(PublishedState());
}
@override
String getStatus() => 'Under Review';
}
class PublishedState implements DocumentState {
@override
void publish(Document doc) {
print('Already published.');
}
@override
String getStatus() => 'Published';
}
class Document {
DocumentState _state = DraftState();
void setState(DocumentState state) => _state = state;
void publish() => _state.publish(this);
String getStatus() => _state.getStatus();
}
void main() {
var doc = Document();
print(doc.getStatus()); // 초안
doc.publish(); // 검토 중으로 이동...
print(doc.getStatus()); // 검토 중
doc.publish(); // 문서가 게시되었습니다!
print(doc.getStatus()); // 게시됨
}각 상태 클래스는 publish() 동작을 다르게 처리하며 문서를 다음 상태로 전환할 수 있습니다. Document 클래스는 현재 상태를 확인하기 위한 조건문이 필요하지 않습니다. 단순히 현재 활성화된 상태 객체에 위임할 뿐입니다. 이 패턴은 주문 처리, 미디어 플레이어 또는 워크플로우 시스템과 같이 뚜렷한 행동 모드를 가진 객체에 이상적입니다.
챌린지
쉬움상태(State) 패턴을 사용하여 신호등 시스템을 만들어 봅시다! 각 상태가 신호등의 색상을 결정하고 다음 상태로 전환되는 방식을 정의하는, 여러 상태를 순환하는 신호등을 만들게 됩니다.
코드는 다음 두 개의 파일로 구성됩니다:
traffic_light.dart: 이 파일에는 상태 클래스들과 신호등 컨텍스트(context)가 포함됩니다. 두 개의 메서드를 가진 추상 클래스TrafficLightState를 생성하세요: 현재 신호등 색상을 반환하는String getColor()와 신호등을 다음 상태로 전환하는void next(TrafficLight light)입니다. 세 개의 구체적인 상태 클래스를 구현하세요:RedState- 색상으로'RED'를 반환하고,next()가 호출될 때'Stop! Light is red.'를 출력한 후GreenState로 전환합니다.GreenState- 색상으로'GREEN'을 반환하고,next()가 호출될 때'Go! Light is green.'를 출력한 후YellowState로 전환합니다.YellowState- 색상으로'YELLOW'를 반환하고,next()가 호출될 때'Caution! Light is yellow.'를 출력한 후RedState로 전환합니다.
RedState에서 시작하는TrafficLight클래스(컨텍스트)를 생성하세요. 이 클래스는 현재 상태를 변경하는setState()메서드, 현재 상태에 위임하는getColor()메서드, 그리고 현재 상태의next()를 호출하는change()메서드를 가져야 합니다.main.dart: 신호등 파일을 임포트하고 상태 패턴이 작동하는 모습을 보여주세요.TrafficLight를 생성하고 초기 색상을 출력합니다. 그런 다음change()를 세 번 호출하고, 각 변경 후에 색상을 출력하세요. 이를 통해 신호등이 모든 상태를 순환하고 다시 처음으로 돌아오는 것을 확인할 수 있습니다.
TrafficLight 클래스가 동작을 결정하기 위해 어떠한 조건문도 필요로 하지 않는다는 점에 주목하세요. 각 상태는 자신의 색상과 다음에 올 상태를 스스로 알고 있습니다. 신호등은 단순히 현재 활성화된 상태에 동작을 위임할 뿐입니다!
예상 출력:
RED
Stop! Light is red.
GREEN
Go! Light is green.
YELLOW
Caution! Light is yellow.
RED치트 시트
상태 패턴(State pattern)은 객체의 내부 상태가 변경될 때 객체의 동작을 변경할 수 있도록 합니다. 복잡한 조건문을 사용하는 대신, 각 상태를 자체 클래스로 캡슐화합니다.
이 패턴은 다음과 같이 구성됩니다:
- Context: 현재 상태에 대한 참조를 유지합니다.
- State classes: 가능한 각 상태에 대한 동작을 정의합니다.
기본 구조:
abstract class DocumentState {
void publish(Document doc);
String getStatus();
}
class DraftState implements DocumentState {
@override
void publish(Document doc) {
print('Moving to review...');
doc.setState(ReviewState());
}
@override
String getStatus() => 'Draft';
}
class Document {
DocumentState _state = DraftState();
void setState(DocumentState state) => _state = state;
void publish() => _state.publish(this);
String getStatus() => _state.getStatus();
}컨텍스트는 동작을 현재 상태 객체에 위임합니다. 각 상태 클래스는 동작을 다르게 처리하며 다음 상태로 전환할 수 있습니다. 이를 통해 현재 상태를 확인하기 위한 조건문이 필요하지 않게 됩니다.
주문 처리, 미디어 플레이어 또는 워크플로 시스템과 같이 뚜렷한 동작 모드가 있는 객체에 이상적입니다.
직접 해보기
import 'traffic_light.dart';
void main() {
// TODO: TrafficLight 인스턴스 생성
// TODO: 초기 색상 출력
// TODO: change()를 호출하고 색상을 출력 (모든 상태를 순환하기 위해 3번 반복)
// 첫 번째 변경: RED -> GREEN
// 두 번째 변경: GREEN -> YELLOW
// 세 번째 변경: YELLOW -> RED
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.