풀스택개발자를 지향하는 진쓰의 디자인패턴 - 상태패턴 블로그 포스팅 시작하겠습니다.
의도
- 객체 자신의 내부상태에 따라 행위를 변경하는 효과를 주고자 할 때 사용합니다.
활용
- 객체 행위는 상태에 따라 달라질 수 있다. 객체의 상태에 따라서 프로그램이 실행 중 행위가 바뀌어야할 때 활용할 수 있습니다.
- 객체 상태에 따라 수많은 if를 갖도록 구현해야하는데 이를 피해보고자 할 때 사용합니다.
역시 개발자는 코드를 보면서 공부를 해야제맛이죠.
예제상황 살펴보시겠습니다.
- Edit 프로그램을 구현하려 한다. 하나의 문서를 열 수 있으며, 문서가 수정상태일 경우, => 문서의 저장, 열기, 종료 기능을 처리하는 방법은, 문서가 수정상태가 아닌 경우의 => 처리 방법을 다르게 동작한다고 한다. |
코드리뷰
- 구조
State.java // 작명을 잘못한것같애요. UML부분에 이유를 설명드리겠습니다. |
public interface State { public void open(); public void close(); public void save(); public void edit(String text); } |
InitState.java State를 implements 하여 구현하였습니다. 앞서배웠던 싱글톤 패턴으로 작성되어있는것도 살펴보실수 있습니다. |
public class InitState implements State { private InitState(){} private static InitState init; public static InitState getInstance(){ if(init ==null) init = new InitState(); return init; }; @Override public void open() { //System.out.println("새로 문서가 열렸습니다."); } @Override public void close() { System.out.println("문서 수정없이 문서가 닫혔습니다."); } @Override public void save() { System.out.println("저장할 것이 없습니다."); } @Override public void edit(String text) { System.out.println("init 상태 -> modify상태 "); EditEngine.setState(ModifyState.getInstance()); } } |
ModifyState.java |
public class ModifyState implements State { private ModifyState(){} private static ModifyState modify; public static ModifyState getInstance(){ if(modify ==null) modify = new ModifyState(); return modify; }; @Override public void open() { System.out.println("이미 열려있는 파일이 있습니다.파일을 저장하고 엽니다."); save(); } @Override public void close() { System.out.println("수정된 사항이있습니다. 파일을 저장하고 종료합니다."); save(); } @Override public void save() { System.out.println("현재내용을 저장합니다."); EditEngine.setState(InitState.getInstance()); } @Override public void edit(String text) { System.out.println("편집 상태 -> 편집상태 (상태변화없음)"); } } |
EditEngine.java 여기서 EditEngine은 state를 가지고 있는데, public static으로 선언되어있어서, State 인터페이스를 implements한 클래스들이 접근할 수 있도록 만들어 놓았습니다. |
public class EditEngine { private String text =""; private static State myState = InitState.getInstance(); public void setText(String text){ this.text = text; } public String getText(){ return text; } public static void setState(State state){ myState = state; } public void open(){ myState.open(); System.out.println("문서가 open되었습니다."); } public void close(){ myState.close(); System.out.println("문서가 종료 되었습니다."); } public void edit(String text){ myState.edit(text); System.out.println("문서가 편집되었습니다"); } public void save(){ myState.save(); } } |
.
Main.java |
public class Main { public static void main(String[] args) { EditEngine edit = new EditEngine(); edit.open(); edit.edit("안녕"); edit.save(); edit.save(); System.out.println("\n\n"); edit.open(); edit.edit("Jinss Programming Lecture"); edit.open(); edit.close(); System.out.println("\n\n"); edit.open(); edit.edit("끝내자"); edit.close(); } } |
결과화면
UML
UML 설명
- State에 문서가 가질수있는 상태 혹은 동작 들을 인터페이스로 구현하였습니다. 음... 동작이라는 표현이 더 와닿는것 같기도합니다.
어쨌든 State 인터페이스를 상속받아 InitState와 ModifyState 를 각각 두웠습니다.
덕분에 InitState일때와, ModifyState일때 open, close, save, edit 라는 행위를 할때는 State에 따라 다르게 동작하게 됩니다.
그러고보니 인터페이스인 State는 막상 State라는 의미이기보단 Behavior? 라는게 더 알맞는 작명일것 같습니다.
뭐 개발자 나름이니깐 저는 그렇게 판단이 되네요.
어쩄든 EditEngine은 State를 가지고있는 has a 관계를 형성하고있습니다.
Main에서 EditEngine을 생성하고 단지 open, close, save, edit만 하면 상태에 따라서 알아서 착착착 다르게 호출되며 돌아가게 됩니다.
그리고 EditEnngine는, setState(state: State): void 를 static method로 선언해서, InitState와 ModfityState에서 접근하여 상태를 바꿀 수 있도록 해놓았습니다.
EditEngine은 State인터페이스 변수를 두고있고, 현재 상태를 InitState혹은 ModifyState 로 갱신해야되니 뚫어놓아야겠죠?
정독해주셔서 감사합니다 :)
'소프트웨어공학 > 디자인패턴 - JAVA' 카테고리의 다른 글
추상 팩토리 패턴 (Abstract factory pattern) (0) | 2020.05.09 |
---|---|
전략 패턴 Strategy pattern (0) | 2017.06.10 |
어댑터 패턴 Adapter Pattern (0) | 2017.06.10 |
팩토리 메소드 Factory method (0) | 2017.06.10 |
싱글톤 패턴 Singleton pattern (0) | 2017.06.09 |