Skip to content

refactoring to patterns replace state sltering conditionals with state

Jongbin Oh edited this page Jun 8, 2013 · 2 revisions

Replace State-Altering Conditionals with State

한줄요약

  1. 상태변경 조건문들을 state 패턴으로 고쳐보자
  2. 즉, 복잡한 if else 를 제거한다는 소리

상태란? 상태변경이란?

  1. 그림을 보자 1

  2. 상태

  3. requested - 사용자의 권한요청 중

  4. claimed - 관리자 심사 중

  5. granted - 허가됨

  6. denied - 거부됨

  7. 상태변경

  8. public void claimedBy(SystemAdmin admin) 1. requested -> claimed

  9. public void grantedBy(SystemAdmin admin) 1. 1. claimed -> granted

  10. public void deniedBy(SystemAdmin admin) 1. claimed -> denied

  11. 상태변경시 사전조건

  12. granted 가 되려면 claimed 이어야 함

  13. 모든 상태 변경의 관리자가 동일해야 함 (심사중인 관리자만 허가상태로 변경 가능)

state 패턴

  1. 그림을 보자

2

  1. strategy 패턴과 비교
  2. 그림을 보자

3

  1. 모양은 비슷해도 동기가 다르다 - 상태전이, 상황에 맞는 로직 선택
  2. 절차도 다르다

복잡한 예제

  1. 그림을 보자
  2. 유닉스 조건이 추가됨 - if else 가 참기 힘들 정도로 많아졌다

4

  1. 복잡해진 코드

    public void grantedBy(SystemAdmin admin) { if (!state.equals(CLAIMED) && !state.equals(UNIX_CLAIMED)) return; if (!this.admin.equals(admin)) return;

       if (profile.isUnixPermissionRequired() && state.equals(UNIX_CLAIMED))
         isUnixPermissionGranted = true;
       else if (profile.isUnixPermissionRequired() &&
         !isUnixPermissionGranted()) {
         state = UNIX_REQUESTED;
         notifyUnixAdminsOfPermissionRequest();
         return;
       }
       state = GRANTED;
       isGranted = true;
       notifyUserOfPermissionRequestResult();
    

    }

  2. 사전조건에 UNIX_CLAIMED 추가

  3. 변경 상태에 UNIX_REQUESTED 추가

리팩터링

  1. 상태 클래스 만들자 - Replace Type Code with Class 참고

     public class PermissionState {
       
     	private String name;
     	private PermissionState(String name) {
     		this.name = name;
     	}
     	  
     	public final static PermissionState REQUESTED = new PermissionState("REQUESTED");
     	public final static PermissionState CLAIMED = new PermissionState("CLAIMED");
     	public final static PermissionState GRANTED = new PermissionState("GRANTED");
     	public final static PermissionState DENIED = new PermissionState("DENIED");
     	  
     	public final static PermissionState UNIX_REQUESTED = new PermissionState("UNIX_REQUESTED");
     	public final static PermissionState UNIX_CLAIMED = new PermissionState("UNIX_CLAIMED");
     	  
     	public String toString() {
     		return name;
     	}
     }
    
  2. 문자열이었던 state의 타잎을 상태클래스 PermissionState 로 변경

  3. get, set 추가

  4. PermissionState getState()

  5. void setState(PermissionState state)

  6. 각 세부 상태별로 subclass 작성

  7. 그림을 보자

  8. PermissionState는 abstracte로

  9. 생성 코드 변경

    //public final static PermissionState REQUESTED = new PermissionState("REQUESTED"); public final static PermissionState REQUESTED = new PermissionRequested(); // super("REQUESTED");

상태 변경 함수를 이동 시킨다

  1. SystemPermission 에 있는 상태변경 함수

  2. claimedBy(), deniedBy(), grantedBy()

  3. 세부 상태 클래스로 이동

  4. 조건문 사라짐

    class PermissionRequested extends PermissionState... public void claimedBy(SystemAdmin admin, SystemPermission permission) { if (!permission.getState().equals(REQUESTED) && !permission.getState().equals(UNIX_REQUESTED)) return;

       	permission.willBeHandledBy(admin);
    
       	if (permission.getState().equals(REQUESTED))
       		permission.setState(CLAIMED);
       	else if (permission.getState().equals(UNIX_REQUESTED))
       		permission.setState(UNIX_CLAIMED);
       }
    

    class PermissionRequested extends Permission... public void claimedBy(SystemAdmin admin, SystemPermission permission) { permission.willBeHandledBy(admin); permission.setState(CLAIMED); }

  5. 사전조건이 이미 충족 되었음 - claimedBy() 는 PermissionRequested 에만 존재

  6. 마찬가지로 deniedBy(), grantedBy() 는 PermissionClaimed 에만 존재

     class PermissionClaimed extends PermissionState ...
     	public void deniedBy(SystemAdmin admin, SystemPermission permission) {
     		if (!permission.getAdmin().equals(admin))
     			return;
     
     		permission.setIsGranted(false);
     		permission.setIsUnixPermissionGranted(false);
     		permission.setState(DENIED);
     		permission.notifyUserOfPermissionRequestResult();
     	}
     
     	public void grantedBy(SystemAdmin admin, SystemPermission permission) {
     		if (permission.getProfile().isUnixPermissionRequired()
     				&& !permission.isUnixPermissionGranted()) {
     			permission.setState(UNIX_REQUESTED);
     			permission.notifyUnixAdminsOfPermissionRequest();
     			return;
     		}
     		permission.setState(GRANTED);
     		permission.setIsGranted(true);
     		permission.notifyUserOfPermissionRequestResult();
     	}
    

PermissionState 추상클래스로

  1. 추상클래스, 아무일도 하지않는 상태변경함수를 인터페이스용으로 가짐

     abstract class PermissionState {
       public String toString();
       public void claimedBy(SystemAdmin admin, SystemPermission permission) {}
       public void deniedBy(SystemAdmin admin, SystemPermission permission) {}
       public void grantedBy(SystemAdmin admin, SystemPermission permission) {}
     }
    
Clone this wiki locally