풀스택개발자를 지향하는 진쓰의 디자인패턴 - 상태패턴 블로그 포스팅 시작하겠습니다.


의도

 - 객체 자신의 내부상태에 따라 행위를 변경하는 효과를 주고자 할 때 사용합니다.



활용

- 객체 행위는 상태에 따라 달라질 수 있다. 객체의 상태에 따라서 프로그램이 실행 중 행위가 바뀌어야할 때 활용할 수 있습니다.


- 객체 상태에 따라 수많은 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 로 갱신해야되니 뚫어놓아야겠죠?



정독해주셔서 감사합니다 :)




+ Recent posts