Writing /volume1/Web/Public/dokuwiki/data/log/deprecated/2024-11-15.log failed

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

次のリビジョン
前のリビジョン
study:java:design_pattern:state [2008/09/20 04:31] – created bananastudy:java:design_pattern:state [2010/10/16 02:09] (現在) banana
行 16: 行 16:
  
 자, 그럼 스테이트 패턴 클래스 다이어그램을 살펴볼까요? 자, 그럼 스테이트 패턴 클래스 다이어그램을 살펴볼까요?
 +
 +
  
 ===== Class Diagram ===== ===== Class Diagram =====
 {{:study:java:design_pattern:state.jpg|State Pattern}} {{:study:java:design_pattern:state.jpg|State Pattern}}
 +
 +클래스 다이어그램을 살펴보면 어디서 본 것 같지 않나요? 맞습니다. 스트래티지 패턴과 모양이 비슷합니다.
 +하지만 이 두 패턴은 용도에 있어서 차이가 있습니다.
 +
 +스테이트 패턴을 사용할 때는 상태 객체에 일련의 행동이 캡슐화됩니다. 상황에 따라 Context 객체에서
 +여러 상태 객체 중 한 객체에게 모든 행동을 맡기게 되죠. 그 객체의 내부 상태에 따라 현재 상태를
 +나타내는 객체가 바뀌게 되고, 그 결과로 컨텍스트 객체의 행동도 자연스럽게 바뀌게 됩니다. 클라이언트
 +는 상태 객체에 대해서 거의 아무것도 몰라도 됩니다.
 +
 +하지만 스트래티지 패턴을 사용할 때는 일반적으로 클라이언트에서 컨텍스트 객체한테 어떤 전략 객체를
 +사용할지를 지정해 줍니다. 스트래티지 패턴은 주로 실행시에 전략 객체를 변경할 수 있는 유연성을 제공
 +하기 위한 용도로 쓰이죠. 보통 가장 적합한 전략 객체를 선택해서 사용할게 됩니다.
 +
 +일반적으로 스트래티지 패턴은 서브클래스를 만드는 방법을 대신하여 유연성을 극대화하기 위한 용도로 쓰입니다.
 +상속을 이용해서 클래스의 행동을 정의하다 보면 행동을 변경해야 할 때 마음대로 변경하기가 힘들죠. 하지만
 +스트래티지 패턴을 사용하면 구성을 통해 행동을 정의하는 객체를 유연하게 바꿀 수 있습니다.
 +
 +스테이트 패턴은 컨텍스트 객체에 수많은 조건문을 집어넣는 대신에 사용할 수 있는 패턴이라고 생각하면 됩니다.
 +행동을 상태 객체 내에 캡슐화시키면 컨텍스트 내의 상태 객체를 바꾸는 것만으로도 컨텍스트 객체의 행동을
 +바꿀 수 있으니까요.
 +
 +
 +
 +===== Example =====
 +스테이트 패턴을 적용한 예로 뽑기 기계(%%Gumball Machine%%)를 살펴보겠습니다.
 +먼저 클래스 다이어그램을 살펴볼까요?
 +{{:study:java:design_pattern:gumballmachine.jpg|Gumball Machine}}
 +
 +스테이트 패턴 클래스 다이어그램에서 Context에 해당하는 것이 %%GumballMachine%% 클래스입니다.
 +
 +
 +===== GumballMachine Class =====
 +<code java>
 +public class GumballMachine {
 +    State soldOutState;
 +    State noQuarterState;
 +    State hasQuarterState;
 +    State soldState;
 +    State winnerState;
 +
 +    State state = soldOutState;
 +    int count = 0;
 +
 +    public GumballMachine(int numberGumballs) {
 +       soldOutState = new SoldOutState(this);
 +       noQuarterState = new NoQuarterState(this);
 +       hasQuarterState = new HasQuarterState(this);
 +       soldState = new SoldState(this);
 +       winnerState = new WinnerState(this);
 +       this.count = numberGumballs;
 +       if (numberGumballs > 0) {
 +           state = noQuarterState;
 +       }
 +       
 +    }
 +
 +    public void insertQuarter(){
 +        state.insertQuarter();
 +    }
 +    
 +    public void ejectQuarter() {
 +        state.ejectQuarter();
 +    }
 +
 +    public void turnCrank() {
 +        state.turnCrank();
 +        state.dispense();
 +    }
 +
 +    void setState(State state) {
 +        this.state = state;
 +    }
 +
 +    void releaseBall() {
 +        System.out.println("A gumball comes rolling out the slot...");
 +        if (count != 0) {
 +            count = count -1;
 +        }
 +    }
 +
 +    public int getCount() {
 +        return this.count;
 +    }
 +
 +    public State getSoldOutState() {
 +        return soldOutState;
 +    }
 +
 +    public State getNoQuarterState() {
 +        return noQuarterState;
 +    }
 +
 +    public State getHasQuarterState() {
 +        return hasQuarterState;
 +    }
 +
 +    public State getSoldState() {
 +        return soldState;
 +    }
 +
 +    public State getWinnerState() {
 +        return winnerState;
 +    }
 +}
 +</code>
 +
 +===== NoQuarterState Calss =====
 +상태를 구현해 볼 때가 되었습니다. 우선 **%%NoQuarterState%%**부터 시작해 봅시다.
 +<code java>
 +public class NoQuarterState implements State {
 +    GumballMachine gumballMachine;
 +
 +    public NoQuraterState(GumballMachine gumballMachine) {
 +        this.gumballMachine = gumballMachine;
 +    }
 +
 +    public void insertQuarter() {
 +        System.out.println("동전을 넣으셨습니다.");
 +        gumballMachine.setState(gumballMachine.getHasQuarterState());
 +    }
 +
 +    public void ejectQuarter() {
 +        System.out.println("동전을 넣어주세요.");
 +    }
 +
 +    public void turnCrank() {
 +        System.out.println("동전을 넣어주세요.");
 +    }
 +
 +    public void dispense() {
 +        System.out.println("동전을 넣어주세요.");
 +    }
 +}
 +</code>
 +
 +
 +
 +===== HasQuarterState Class =====
 +이제 **%%GumballMachine%%** 클래스하고 상태 클래스가 어떤 식으로 맞물려 돌아가는지 어느 정도
 +감히 잡힐 것 같군요. 그럼 **%%HasQuarterState%%**와 **%%SoldSate%%** 클래스도 구현해 볼까요?
 +<code java>
 +public class HasQuarterState implements State {
 +     Random randomWinner = new Random(System.currentTimeMillis());
 +     GumballMachine gumballMachine;
 +
 +     public HasQuarterState(GumballMachine gumballMachine) {
 +        this.gumballMachine = gumballMachine;
 +     }
 +
 +     public void insertQuarter() {
 +        System.out.println("동전은 한 개만 넣어주세요.");
 +     }
 +
 +     public void ejectQuarter() {
 +        System.out.println("동전이 반환됩니다.");
 +        gumballMachine.setState(gumballMachie.getNoQuarterState());
 +     }
 +
 +     public void turnCrank() {
 +        System.out.println("손잡이를 돌리셨습니다.");
 +        int winner = randomWinner.nextInt(10);
 +        if((winner==0) && (gumballMachine.getCount() > 1)) {
 +           gumballMachine.setState(gumballMachine.getWinnerState());
 +        } else {
 +           gumballMachine.setState(gumballMachine.getSoldState());
 +        }
 +     }
 +
 +     public void dispense() {
 +        System.out.println("알맹이가 나갈 수 없습니다.");
 +     }
 +}
 +</code>
 +
 +
 +
 +===== SoldState Class =====
 +**%%SolidState%%** 클래스도 살펴봅시다.
 +<code java>
 +public class SolidState implements State {
 +     GumballMachine gumballMachine;
 +
 +     public SolidState(GumballMachine gumballMachine) {
 +         this.gumballMachine = gumballMachine;
 +     }
 +
 +     public void insertQuarter() {
 +         System.out.println("잠시만 기다려 주세요. 알맹이가 나가고 있습니다.");
 +     }
 +
 +     public void ejectQuarter() {
 +         System.out.println("이미 알맹이를 뽑으셨습니다.");
 +     }
 +
 +     public void turnCrank() {
 +         System.out.println("손잡이는 한 번만 돌려주세요.");
 +     }
 +
 +     public void dispense() {
 +         gumballMachine.releaseBall();
 +         if (gumballMachine.getCount() > 0) {
 +             gumballMachine.setState(gumballMachine.getNoQuarterState());
 +         } else {
 +             System.out.println("Oopse, out of gumballs!.");
 +             gumballMachine.setState(gumballMachine.getSoldState());
 +         }
 +     }
 +}
 +</code>
 +===== SoldOutState Class =====
 +<code java>
 +public class SoldOutState implements State {
 +    GumballMachine gumballMachine;
 +
 +    public SoldOutState(GumballMachine gumballMachine) {
 +         this.gumballMachine = gumballMachine;
 +    }
 +
 +    public void insertQuarter() {
 +         System.out.println("죄송합니다. 매진되었습니다.");
 +    }
 +
 +    public void ejectQuarter() {
 +         System.out.println("죄송합니다. 매진되었습니다.");
 +    }
 +
 +    public void turnCrank() {
 +         System.out.println("죄송합니다. 매진되었습니다.");
 +    }
 +
 +    public void dispense() {
 +         System.out.println("죄송합니다. 매진되었습니다.");
 +    }
 +}
 +</code>
 +===== WinnerState Class =====
 +<code java>
 +public class WinnerState implements State {
 +     GumballState gumballState;
 +
 +     public WinnerState(GumballState gumballState) {
 +         this.gumballState = gumballState;
 +     }
 + 
 +     public void insertQuarter() {
 +         System.out.println("이미 알맹이를 뽑으셨습니다.");
 +     }
 +
 +     public void ejectQuarter() {
 +         System.out.println("이미 알맹이를 뽑으셨습니다.");
 +     }
 +
 +     public void turnCrank() {
 +         System.out.println("이미 알맹이를 뽑으셨습니다.");
 +     }
 +
 +     public void dispense() {
 +         System.out.println("축하드립니다! 알맹이를 하나 더 받으실 수 있습니다.");
 +         gumballMachine.releaseBall();
 +         if (gumballMachine.getCount() == 0) {
 +             gumballMachine.setState(gumballMachine.getSoldOutState());
 +         } else {
 +             System.out.println("더 이상 알맹이가 없습니다.");
 +             gumballMachine.setState(gumballMachine.getSoldOutState());
 +         }
 +     }
 +}
 +</code>
  

QR Code
QR Code study:java:design_pattern:state (generated for current page)