ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Design Pattern] State Pattern example
    programing/etc 2018. 11. 30. 22:45

    안녕하세요, Einere입니다.

    (ADblock을 꺼주시면 감사하겠습니다.)


    오늘은 State Pattern example을 java로 구현한 것을 공유하고자 합니다.

     

    간단하게, ATM기기를 구현합니다.

    ATM기기는 총 3가지 상태가 존재합니다.

    1. noCard
    2. hasCard
    3. noCash

    noCard상태는 말그대로 카드가 삽입되지 않은 상태입니다.

    hasCard는 카드가 삽입된 상태입니다.

    noCash는 기기가 보유한 현금이 없는 상태입니다.

     

    ATM기기는 총 3가지 동작을 합니다.

     

    1. insertCard
    2. ejectCard
    3. withdrawCash

     

     

     

    각각 카드를 삽입하고, 빼고, 출금을 하는 동작입니다.

     

     

    class diagram으로 나타내자면 위와 같습니다.

    물론 getter와 setter는 생략했습니다.

     

    위와 같은 ATM기기를 State Pattern을 사용해 구현해보겠습니다.

     

     

     

    ATMMachine

    public class ATMMachine {     private ATMState noCardState = null;     private ATMState hasCardState = null;     private ATMState noCashState = null;     private ATMState currentState = null;     private int currentCash = 10000;      public ATMMachine() {         noCardState = new NoCard();         hasCardState = new HasCard();         noCashState = new NoCash();         currentState = noCardState;     }      public int getCurrentCash() {         return currentCash;     }      public ATMState getNoCardState() {         return noCardState;     }      public ATMState getHasCardState() {         return hasCardState;     }      public ATMState getNoCashState() {         return noCashState;     }      public void setCurrentCash(int currentCash) {         this.currentCash = currentCash;     }      public void insertCard() {         currentState.insertCard(this);     }      public void ejectCard() {         currentState.ejectCard(this);     }      public void withdrawCash(int money) {         currentState.withdrawCash(this, money);     }      public void setState(ATMState state) {         this.currentState = state;     } } 

    ATM기는 모든 state를 filed로 가지고 있습니다.

    현재 상태를 나타낼 currentState도 있습니다.

    현재 기기에 남은 현금인 currentCash도 있습니다.

     

    생성자에서 모든 상태의 instance를 생성하여 할당합니다.

    currentCash는 private이므로, getter와 setter를 만들어 줍니다.

    machine이 가지고 있는 state를 얻기 위한 getter도 만들어 줍니다. 해당 getter는 concrete state class에서 사용됩니다.

     

     

     

    ATMState

    public interface ATMState {     void insertCard(ATMMachine machine);     void ejectCard(ATMMachine machine);     void withdrawCash(ATMMachine machine, int money); }

    ATMMachine의 상태가 추가되거나, 동작이 추가될 경우를 대비하여, interface를 정의합니다.

    현재는 카드삽입, 카드제거, 현금인출 세가지 동작만 합니다.

     

     

     

    NoCard

    public class NoCard implements ATMState {     @Override     public void insertCard(ATMMachine machine) {         System.out.println("[insertCard] card inserted");         machine.setState(machine.getHasCardState());     }      @Override     public void ejectCard(ATMMachine machine) {         System.out.println("[ejectCard] no card to eject");     }      @Override     public void withdrawCash(ATMMachine machine, int money) {         System.out.println("[withdrawCash] no card inserted");     } }

    ATMMState를 implement합니다.

    현재 카드가 없는 상태라면, 카드삽입을 제외한 모든 동작은 불가능해야 합니다.

    카드삽입을 한 경우, machine의 hasCardState를 얻어서, machine의 currentState로 설정합니다.

     

     

     

    HasCard

    public class HasCard implements ATMState {     @Override     public void insertCard(ATMMachine machine) {         System.out.println("[insertCard] already card inserted");     }      @Override     public void ejectCard(ATMMachine machine) {         System.out.println("[ejectCard] card ejected");         machine.setState(machine.getNoCardState());     }      @Override     public void withdrawCash(ATMMachine machine, int money) {          int currentCash = machine.getCurrentCash();         if(currentCash > money){             System.out.println("[withdrawCash] withdraw " + money);              int remainCash = currentCash - money;             machine.setCurrentCash(remainCash);             System.out.println("[withdrawCash] remain cash in machine : " + remainCash);         }         else if (currentCash == money){             System.out.println("[withdrawCash] now, no cash in machine");             machine.setState(machine.getNoCashState());         }         else{             System.out.println("[withdrawCash] no cash to withdraw in machine");         }     } }

    ATMMState를 implement합니다.

    카드가 삽입된 상태이므로 카드가 재삽입이 안되며, 제거는 가능합니다.

    현금인출을 할 경우, 기기에 잔금이 충분하다면 인출을합니다.

    잔금이 0원이 된다면 noCash state가 됩니다.

    잔금이 부족한 경우 알림만 출력합니다.

     

     

     

    NoCash

    public class NoCash implements ATMState {     @Override     public void insertCard(ATMMachine machine) {         System.out.println("[insertCard] already card inserted");     }      @Override     public void ejectCard(ATMMachine machine) {         System.out.println("[ejectCard] eject card");         machine.setState(machine.getNoCardState());     }      @Override     public void withdrawCash(ATMMachine machine, int money) {         System.out.println("[withdrawCash] no cash to withdraw in machine");     } }

    ATMMState를 implement합니다.

    현금이 없는 상태이므로 카드제거만 할 수 있습니다.

    (noCash state로 진입하기 위한 전 상태가 hasCard state이므로, 카드 재삽입이 불가능합니다.)

     

     

     

    Main

    public class Main {     public static void main(String[] args) {         ATMMachine atm = new ATMMachine();         atm.withdrawCash(100);         atm.ejectCard();         atm.insertCard();         atm.insertCard();         atm.withdrawCash(5000);         atm.withdrawCash(7000);         atm.withdrawCash(5000);         atm.insertCard();         atm.withdrawCash(1000);         atm.ejectCard();     } }

    ATMMachine을 하나 생성합니다.

    그리고 여러가지 테스트를 합니다.

     

     

    결과는 위와 같습니다.

    댓글

Designed by black7375.