스테이트 패턴(State Pattern)이란?
어떠한 객체가 특정 상태에 따라 다른 행동을 해야할 때 사용할 수 있는 패턴을 스테이트 패턴(State Pattern)이라고 한다. if문이나 switch 문을 통해 객체의 상태를 객체내에서 충분히 정의할 수 있다. 다만 상태의 경우가 많아질수록 내부적으로 처리해야하는 코드가 많아지고 객체 코드가 지저분해지며 유지 보수가 점점 어려워진다. 따라서 상태를 캡슐화하여 이를 객체 단위로 유지한다. 물론 객체내 코드가 단순해지는 장점은 있지만 분명 단점이 존재한다. 상태마다 클래스를 정의해야하므로 프로젝트내 클래스가 다소 많아질 수도 있다. 이를 적절하게 사용해야 할 것이다.
- 코드 가독성 증가
- 객체내 코드 단순화
- 프로젝트내 객체가 많아져 관리가 어려워질 수 있음.
예시
Counter라는 객체를 생성한다. Counter는 현재의 인덱스 값에 따라 첫 번째, 마지막, 중간으로 상태를 구분한다. 외부에선 이 인덱스 값을 증가 및 감소할 수 있다.
IIndex
객체의 상태를 객체화하기전에 캡슐화를 위한 인터페이스이다.
public interface IIndex
{
string GetDescription();
}
Index 클래스
IIndex 인터페이스를 상속받아 First, Last, Middle에 대한 상태 객체를 생성한다. 각 객체는 상태에 대한 설명을 반환하는 함수인 GetDescription을 구현한다.
FirstIndex
public class FirstIndex : IIndex
{
public string GetDescription() => "First";
}
LastIndex
public class LastIndex : IIndex
{
public string GetDescription() => "Last";
}
MiddleIndex
public class MiddleIndex : IIndex
{
public string GetDescription() => "Middle";
}
Counter
Counter는 전체 count값을 가지고 있고 그 값과 현재 인덱스 값을 비교하여 상태를 결정한다.
public class Counter
{
private readonly int _count;
private int _idx = 0;
public IIndex Index { get; private set; }
public Counter(int count)
{
_count = count;
Index = GetIndex(_count, _idx);
}
public void Increase()
{
_idx++;
Index = GetIndex(_count, _idx);
}
public void Decrease()
{
_idx--;
Index = GetIndex(_count, _idx);
}
public int GetIndex() => _idx;
public string GetDescription() => Index?.GetDescription() ?? throw new Exception($"{Index} is null");
private static IIndex GetIndex(int count, int index)
{
if (index == 0)
return new FirstIndex();
if (index == count - 1)
return new LastIndex();
return new MiddleIndex();
}
}
Main
console로부터 감소, 증가에 대한 키워드를 입력받아 Counter의 상태를 변경한다. 변경할 때마다 현재 인덱스와 상태에 대한 설명을 출력한다.
static void Main(string[] args)
{
var countStr = Console.ReadLine();
if (!int.TryParse(countStr, out int count))
return;
var counter = new Counter(count);
string input = "";
while((input = Console.ReadLine()) != null)
{
if (input == "END")
break;
if (input == "p" || input == "+")
counter.Increase();
else if (input == "m" || input == "-")
counter.Decrease();
var idx = counter.GetIndex();
var desc = counter.GetDescription();
Console.WriteLine($"index : {idx}, state : {counter.GetDescription()}");
}
}
결과
아래와 같이 Counter의 현재 인덱스 값을 증가 및 감소시키고 그에 맞는 상태 설명에 대한 메세지를 출력하고 있다.
참조
해당 패턴을 공부하면서 사이드 프로젝트로 진행중인 Jaywapp.BuilderWizard에도 적용하였다. 적용한 코드의 commit은 아래와 같다. 실질적으로 적용한 코드이니 예시를 봐도 감이 안올 때 참고하면 좋을 것 같다.
add state pattern, factory pattern · jaywapp/Jaywapp.BuilderWizard@1938cc2
Show file tree Showing 8 changed files with 126 additions and 42 deletions.
github.com
'Software Develop > Design Pattern' 카테고리의 다른 글
싱글톤 패턴 (Singleton Pattern) (0) | 2023.01.16 |
---|---|
빌더 패턴 (Builder Pattern) (0) | 2023.01.13 |
파사드 패턴 (Facade Pattern) (0) | 2023.01.12 |
Inversion Of Control Container, IUnityContainer (0) | 2022.02.24 |
MVVM 패턴 (Model - View - ViewModel) (0) | 2022.02.24 |