ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JAVA]객체 지향 디자인 패턴 - State Pattern(상태 패턴)
    프로그래밍/Java 2022. 3. 22. 20:57
    반응형

    State Pattern이란?

    • 상태의 범위가 정해져 있고, 상태를 객체단위로 관리하고 싶을 때 사용한다. 상태들은 공유해야하는 특성을 갖는다.
    • 구조는 strategy패턴과 거의 동일하여 strategy패턴과 많이 혼동이 오는데 차이점은 state를 알려주고 서로 변경해주어야 한다는 점이다르다.

     

    State Pattern Structure(상태 패턴 구조)

    • Context : 상태 패턴을 이용하는 역할을 수행한다. 하나의 객체에 상태를 조절하는 메소드를 부르는 역할을 한다.
    • State : 인터페이스나 추상 클래스로 외부에서 동일한 방식으로 상태 알고리즘을 호출하는 방법을 명시한다.
    • ConcreteState1, ConcreteState2, ConcreteState3 : State의 실제 알고리즘 구현부와 State가 변경 되는 로직을 구현한다.

    State Pattern Example

    • Induction(인덕션)이 있다고 가졍해 보자. 인덕션의 상태는 켜고, 끄기 상태가 있을 것이다. 이해를 돕기 위함이니 두상태만 하도록 하자.
    • Induction을 turnon하면 켜지는 것이고 turnOff하면 꺼지는 로직을 상태패턴을 이용하여 구현해 보도록 하자.
    • Induction을 이용한 상태패턴 로직은 아래와 같다고 하여 구현해보자.

     

    //state interface
    public interface InductionState {
    	public void turnOn(Induction induction);
    	public void turnOff(Induction induction);
    }
    
    //Onstate 객체
    public class InductionStateOff implements InductionState{
    	@Override
    	public void turnOn(Induction induction) {
    		System.out.println("인덕션이 켜졌습니다.");
    		induction.setState(new InductionStateOn());
        }
    
    	@Override
    	public void turnOff(Induction induction) {System.out.println("인덕션이 꺼진 상태입니다.");}
    }
    
    //Offstate 객체
    public class InductionStateOn implements InductionState{
    
    	@Override
    	public void turnOn(Induction induction) {System.out.println("인덕션이 켜진 상태입니다.");}
    
    	@Override
    	public void turnOff(Induction induction) {
    		System.out.println("인턱션이 꺼집니다.");
    		induction.setState(new InductionStateOff());
    	}
    }
    • induction이 켜져있는 상태에서는 on을 누르면 켜진상태라고 나오고, off를 누르면 꺼진다고 로직을 실행시킨후 꺼진 상태로 바꾸는 형태 off를 누르면 반대의 로직으로 구현하였다.
    public class Induction {
    	
    	private InductionState inductionState = new InductionStateOff();
    	//위와 아래는 동일한 코드입니다.
    	//private InductionState inductionState = null;
    	//public Induction() {
    	//	this.inductionState = new InductionStateOff(); 
    	//}
    	
    	public void setState(InductionState inductionState) {
    		this.inductionState = inductionState;
    	}
    	
    	public void turnOn() {
    		inductionState.turnOn(this); 
    		//inductionState에 의존하여 turnOn이 실행 되므로 
    		//this induction자기 자신을 던져주어 상태값을 바꾸도록 유도한다.
    	}
    	
    	public void turnOff() {
    		inductionState.turnOff(this);
    	}
    }
    • Induction이라는 객체 클래스이다. 객체클래스에서는 turnOn은 상태 클래스에 따라 turnOn을 실행 turnOff은 상태클래스에 따라 turnOff를 실행 시켜 주도록 하였다. 여기서 다형성개념이 들어간 객체 이므로 다형성을 모르면 꼭 숙지 하고 다시 보도록 하자 
    public class InductionTest {
    	public static void main(String[] args) {
    		Induction induction = new Induction();
    		induction.turnOn();
    		induction.turnOff();
    		induction.turnOff();
    		induction.turnOn();
    		induction.turnOn();
    		//출력
    		//인덕션이 켜졌습니다.
    		//인턱션이 꺼집니다.
    		//인덕션이 꺼진 상태입니다.
    		//인덕션이 켜졌습니다.
    		//인덕션이 켜진 상태입니다.
    	}
    }
    • 출력 했을 때는 이렇게 나오게 된다.

    State Pattern 을 사용하는 이유?

    • State패턴을 사용하지 않는다면 위와 같은 코드는 상태에 대한 값을 일일히 정해주어야 하며, 상태값에 따라 if문을 나열하는 형식으로 작성하게 된다. 그러면 가독성도 떨어질 뿐더러, 상태 값이 추가가 된다고 하면 오타나 다른 형식으로든 문제가 발생하게 된다.
    • 그래서 안에서 사용하는 함수만 정의하고 추가하도록 구현하고 내부 상태값에 따라 로직이 구현되도록 한다는 것이다.
    • State Patter은 On이라는 state객체 Off라는 state로 나눠 관리하고자 하는것인데 State라는 것도 객체로 보고 관리 하겠다는 의미이다. 그래서 state가 추가되어도 확장성이 좋다 InductionStateLock이라는 잠금기능이 들어간다고 하여도 context, interface method를 추가하고 InductionStateLock이라는 class객체만 추가하여 유지보수 하면 되기 때문이다.

     

     

    State Pattern과 Strategy Pattern의 차이점 

    • 위에 말은 일반적으로 확장성, 반복성, 분산성이 띈다는 의미이다. 그런데 strategy 패턴과 같다고 느끼는 분들도 있을 수 있다. 처음엔 나도 뭔 차이인지 모랐다.
    • Induction은 State라는 상태값을 가지고 있어야한다. 상태 별로 로직이 달라지기 때문이다. 그리고 그 상태가 바뀌면서 어떤 상태인데 stateObject를 상태값에 넣어 줘야 한다. 이말은 state끼리 유기적으로 변경 되었다는 notifier를 제공해 주어야 한다는 의미이다. 암튼 유기적으로 순환 되어 로직이 발생해야한다는 의미이다. 아래와 같이 말이다.
    //Onstate 객체
    @Override
    public void turnOn(Induction induction) {
        System.out.println("인덕션이 켜졌습니다.");
        induction.setState(new InductionStateOn()); //On객체를 넣어준다
    }
    //Offstate 객체
    @Override
    public void turnOff(Induction induction) {
        System.out.println("인턱션이 꺼집니다.");
        induction.setState(new InductionStateOff());//Off 객체를 넣어준다.
    }
    • Strategy 패턴은 전략에 따라 로직이 구동되고 그냥 그 기능은 끝이다. 유기적으로 state값을 noti줄 필요가 없다.
    • 둘의 차이점을 잘 파악하여 객체 지향적으로 작성하는 부분이 필요한것같다.
    반응형

    댓글

Designed by Tistory.