Menu
Coddy logo textTech

상태 패턴

Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 107개 중 95번째.

State 패턴은 객체의 내부 상태가 changes할 때 해당 객체가 behavior를 변경할 수 있도록 하여, 객체의 클래스가 변경된 것처럼 보이게 합니다. Template Method가 알고리즘 단계를 제어하는 반면, State는 상태별 behavior를 별도의 객체로 캡슐화하고 current 상태에 위임합니다.

Go에서는 상태 인터페이스를 정의하고 서로 다른 동작을 구현하는 구체적인 상태를 생성합니다:

type State interface {
    Handle(d *Document) string
}

type Document struct {
    state State
}

func (d *Document) SetState(s State) {
    d.state = s
}

func (d *Document) Publish() string {
    return d.state.Handle(d)
}

각 상태는 어떤 일이 발생하고 다음에 어떤 상태가 될지를 결정합니다:

type DraftState struct{}

func (s DraftState) Handle(d *Document) string {
    d.SetState(ModerationState{})
    return "Draft submitted for moderation"
}

type ModerationState struct{}

func (s ModerationState) Handle(d *Document) string {
    d.SetState(PublishedState{})
    return "Moderation approved, now published"
}

type PublishedState struct{}

func (s PublishedState) Handle(d *Document) string {
    return "Already published"
}

현재 상태에 따라 동일한 method call이 서로 다른 result를 생성합니다:

doc := &Document{state: DraftState{}}

fmt.Println(doc.Publish())  // 초안이 검토를 위해 제출됨
fmt.Println(doc.Publish())  // 검토 승인됨, 이제 게시됨
fmt.Println(doc.Publish())  // 이미 게시됨

State는 주문 처리 워크플로, UI 구성 요소 또는 동작이 전적으로 current 상태에 따라 달라지는 연결 처리기와 같이 작동 모드가 명확하게 구분되는 객체에 이상적입니다.

challenge icon

챌린지

쉬움

State 패턴을 사용하여 티켓 지원 시스템을 만들어 봅시다! 티켓이 열림, 작업 중, 해결됨의 여러 단계를 거치도록 지원 티켓을 만들고, 각 state가 가능한 작업과 다음에 발생할 일을 결정하도록 합니다.

코드를 세 개의 파일로 구성합니다:

  • state.go: state interface와 티켓 수명 주기의 각 단계를 나타내는 구체적인 state를 Define합니다.

    티켓을 처리하고 잠재적으로 다음 state로 전환하는 TicketState interface와 Handle(t *Ticket) string method를 Create합니다.

    세 가지 state를 Implement합니다:

    • OpenState: handled되면 티켓을 InProgressState로 전환하고 Ticket opened, assigning to support team을 returns합니다.
    • InProgressState: handled되면 ResolvedState로 전환하고 Working on ticket, issue resolved를 returns합니다.
    • ResolvedState: handled되면 동일한 state에 stays하고 Ticket already resolved를 returns합니다.
  • ticket.go: current state를 보유하고 behavior를 해당 state에 delegates하는 티켓 struct를 Create합니다.

    ID field(string)와 state field(TicketState)를 가진 Ticket struct를 Build합니다. 다음 methods를 추가합니다:

    • 티켓의 current state를 changes하는 SetState(s TicketState)
    • current state의 Handle method에 delegates하는 Process() string

    OpenState에서 시작하는 티켓을 returns하는 NewTicket(id string) *Ticket constructor를 Create합니다.

  • main.go: 티켓의 current state에 따라 동일한 action이 서로 다른 results를 만드는 방식을 Demonstrate합니다.

    티켓 ID와 티켓을 Process할 횟수를 Read합니다. 해당 ID로 새 티켓을 Create한 다음, 지정된 횟수만큼 Process()를 call하고 각 result를 별도의 줄에 출력합니다.

다음 inputs가 제공됩니다:

  • Line 1: 티켓 ID
  • Line 2: 티켓을 Process할 횟수

예를 들어, 다음이 given되면:

TKT-001
3

output은 다음과 같아야 합니다:

Ticket opened, assigning to support team
Working on ticket, issue resolved
Ticket already resolved

그리고 다음이 given되면:

TKT-500
5

output은 다음과 같아야 합니다:

Ticket opened, assigning to support team
Working on ticket, issue resolved
Ticket already resolved
Ticket already resolved
Ticket already resolved

그리고 다음이 given되면:

ISSUE-42
1

output은 다음과 같아야 합니다:

Ticket opened, assigning to support team

동일한 티켓에서 Process()를 call할 때마다 서로 다른 results가 생성되는 것을 확인하세요. 티켓이 state를 거치며 이동함에 따라 behavior가 changes합니다. 한 번 resolved되면 아무리 많이 Process해도 resolved 상태로 stays합니다. 티켓 object가 behavior를 changes하는 것처럼 보이지만, 실제로는 서로 다른 state objects에 delegates하고 있습니다!

직접 해보기

package main

import (
	"fmt"
)

func main() {
	// 입력 읽기
	var ticketID string
	var numProcesses int
	fmt.Scanln(&ticketID)
	fmt.Scanln(&numProcesses)

	// TODO: 주어진 ID로 새 티켓 생성

	// TODO: 지정된 횟수만큼 티켓 처리
	// 그리고 각 결과를 별도의 줄에 출력
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 Go 컴파일러