typescript 實現狀態模式

狀態模式

業務邏輯

初級版本

const enum State{
    SOLD_OUT=0,//糖果售完
    NO_QUARTER=1,//沒有硬幣
    HAS_QUARTER=2,//已有硬幣
    SOLD=3,//正在出糖果
    WINNER=4
}
class GumballMachine{
    public state:State;
    count:number;
    public constructor(count:number){
        this.state=State.SOLD
        this.count=count
        if(count>0){
            this.state=State.NO_QUARTER
        }
    }
    //插入硬幣
    public insertQuarter():void{
        let currSte=this.state
        if(currSte==State.HAS_QUARTER){
            console.log('You can\'t insert another quarter')
        }else if(currSte==State.NO_QUARTER){
            this.state=State.HAS_QUARTER
            console.log('You inserted a quarter');
        }else if(currSte==State.SOLD_OUT){
            console.log('you can\'t insert a quarter,the machine is sold out');
        }else if(currSte==State.SOLD){
            console.log('Please wait,we\'re already giving you a gumball');
        }
        else if(currSte==State.WINNER){
            console.log('Please wait,we\'re already giving you a gumball');
        }
    }
    //退出硬幣
    public ejectQuarter():void{
        let currSte=this.state
        if(currSte==State.HAS_QUARTER){
            console.log('Quarter returned');
            this.state=State.NO_QUARTER
        }
        else if(currSte==State.NO_QUARTER){
            console.log('you haven\'t inserted a quarter');
        }
        else if(currSte==State.SOLD){
            console.log('Sorry,you already turned the crank');
        }else if(currSte==State.WINNER){
            console.log('you can\'t eject,you haven\'t inserted a quarter yet')
        }
        else if(currSte==State.SOLD_OUT){
            console.log('you can\'t eject,you haven\'t inserted a quarter yet')
        }
    }
    //轉動曲柄
    public turnCrank():void{
        if(this.state===State.SOLD){
            console.log('Turning twice doesn\'t get you another gumball!');
        }
        else if(this.state===State.NO_QUARTER){
            console.log("you turned but there's no quarter");
        }
        else if(this.state===State.SOLD_OUT){
            console.log("You turned,but there are no gumballs")
        }
        else if(this.state===State.HAS_QUARTER){
            console.log("you turned...")
            if(Math.random()>0.9){
                this.state=State.WINNER
            }else{

                this.state=State.SOLD
            }
            this.dispense();
        }
    }
    //彈出糖果
    public dispense():void{
        if(this.state==State.SOLD){
            console.log("A gumball comes rolling out the slot");
            this.count-=1
            if(this.count==0){
                console.log("Oops,out of gumballs!");
                this.state=State.SOLD_OUT
            }else{
                this.state=State.NO_QUARTER
            }
        }else if(this.state==State.WINNER){
            console.log("two gumball comes rolling out the slot")
            this.count-=2
            if(this.count==0){
                console.log("Oops,out of gumballs!");
                this.state=State.SOLD_OUT
            }else{
                this.state=State.NO_QUARTER
            }
        }else if(this.state==State.NO_QUARTER){
            console.log("You need to pay first");
        }else if(this.state==State.SOLD_OUT){
            console.log("No gumball dispensed");
        }else if(this.state==State.HAS_QUARTER){
            console.log("No gumball dispensed");
        }

    }
    public toString():any{
          if(this.state==State.SOLD){
              return "current State:SOLD"+","+"count:"+this.count
        }else if(this.state==State.NO_QUARTER){
            return "current NO_QUARTER"+","+"count:"+this.count
        }else if(this.state==State.SOLD_OUT){
            return "current SOLD_OUT"+","+"count:"+this.count
        }else if(this.state==State.HAS_QUARTER){
            return "current HAS_QUARTER"+","+"count:"+this.count
        }
    }
}
//測試代碼
let gumballMachine:GumballMachine
gumballMachine=new GumballMachine(5)
console.log(gumballMachine.toString());
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
console.log(gumballMachine.toString());

gumballMachine.insertQuarter()
gumballMachine.ejectQuarter()
gumballMachine.turnCrank()
console.log(gumballMachine.toString());

gumballMachine.insertQuarter()
gumballMachine.turnCrank()
gumballMachine.insertQuarter()
gumballMachine.turnCrank()
gumballMachine.ejectQuarter()
console.log(gumballMachine.toString());
console.log('------------------------');

gumballMachine.insertQuarter()
gumballMachine.insertQuarter()
gumballMachine.turnCrank()
gumballMachine.insertQuarter()
gumballMachine.turnCrank()
gumballMachine.insertQuarter()
gumballMachine.turnCrank()
console.log(gumballMachine.toString());

改良版本

/*
const enum State {
    
    SOLD_OUT = 0,
    NO_QUARTER = 1,
    HAS_QUARTER = 2,
    SOLD = 3,
    WINNER = 4
}
*/
interface State {

    state: State;
    count: number;
    insertQuarter(): void;
    ejectQuarter():void;
    turnCrank():void;
    dispense():void;
}
class SoldOutState implements State{
    state:State;
    count:number;
    gumballMachine:GumballMachine
    constructor(gumballMachine:GumballMachine){
        this.gumballMachine=gumballMachine
    }
    public insertQuarter():void{
        console.log("You can't insert a quarter,the machine is sold out");
    }
    public ejectQuarter():void{
        console.log("You can't eject,you haven't inserted a quater yet");
    }
    public turnCrank():void{
        console.log("you turned,but there are no gumballs");
    }
    public dispense():void{
        console.log("No gumball dispensed");
    }
}

class NoQuarterState implements State {
    state: State
    count: number;
    gumballMachine: GumballMachine
    constructor(gumballMachine: GumballMachine) {
        this.gumballMachine = gumballMachine
    }
    public insertQuarter(): void {
        console.log("You inserted a quarter");
        this.gumballMachine.setState(this.gumballMachine.getHasQuarterState());
    }
    public ejectQuarter() :void{
        console.log('you haven\'t inserted a quarter');
    }
    public turnCrank():void {
        console.log("You turned,but there's no quarter");
    }
    public dispense():void {
        console.log("You need to pay first");
    }
}
class SoldState implements State {
    state: State
    count: number;
    gumballMachine: GumballMachine
    constructor(gumballMachine: GumballMachine) {
        this.gumballMachine=gumballMachine

    }
    public insertQuarter(): void {
        console.log("Please wait,we're already giving you a gumball");
    }
    public ejectQuarter():void {
        console.log("Sorry,you already turned the crank");
    }
    public turnCrank():void {
        console.log("Turning twice doesn't get you another gumball!");
    }
    public dispense():void {
        this.gumballMachine.releaseBall();
        if(this.gumballMachine.getCount()>0){
            this.gumballMachine.setState(this.gumballMachine.getNoQuarterState());
        }else{
            console.log("oops,out of gumballs!");
            this.gumballMachine.setState(this.gumballMachine.getSoldOutState());

        }
    }
}
class HasQuarterState implements State {
    state: State
    count: number;
    gumballMachine: GumballMachine
    constructor(gumballMachine: GumballMachine) {
        this.gumballMachine=gumballMachine
        console.log("has quarter")

    }
    public insertQuarter(): void {
        console.log("you can't insert another quarter");
    }
    public ejectQuarter():void {
        console.log("Quarter returned");
        this.gumballMachine.setState(this.gumballMachine.getNoQuarterState())
    }
    public turnCrank():void {
        console.log("You turned...");
        this.gumballMachine.setState(this.gumballMachine.getSoldState())
    }
    public dispense():void {
        this.gumballMachine.releaseBall();
        if(this.gumballMachine.getCount()>0){
            this.gumballMachine.setState(this.gumballMachine.getNoQuarterState());
        }else{
            console.log("oops,out of gumballs!");
            this.gumballMachine.setState(this.gumballMachine.getSoldOutState());

        }
    }
}
class GumballMachine {
    soldOutState: State;
    noQuarterState: State
    hasQuarterState: State
    soldState: State
    state: State = this.soldOutState
    count: number = 0
    constructor(numberGumballs: number) {
        this.noQuarterState = new NoQuarterState(this);
        this.soldOutState = new SoldOutState(this);
        this.hasQuarterState=new HasQuarterState(this);
        this.soldState=new SoldState(this);
        this.count=numberGumballs
        if (numberGumballs > 0) {
            this.state = this.noQuarterState
        }
    }
    public insertQuarter(): void {
        this.state.insertQuarter();
    }
    public turnCrank(): void {
        this.state.turnCrank();
        this.state.dispense();
    }
    /**
     * setState
     */
    public setState(state: State):void {
        
        this.state = state
    }
    public releaseBall(): void {
        console.log("A gumball comes rolling out the slot...");
        if (this.count != 0) {
            this.count = this.count - 1
        }
    }

    public getHasQuarterState(): State {
        return this.hasQuarterState
    }
    public getCount():number{
        return this.count
    }
    public getNoQuarterState():State{
        return this.noQuarterState
    }
    public getSoldOutState():State{
        return this.soldOutState
    }
    public getSoldState():State{
        return this.soldState
    }
    public toString():string{
        return this.state+':'+this.count
    }
}
let gumballMachine
gumballMachine=new GumballMachine(5)
console.log(gumballMachine.toString());

gumballMachine.insertQuarter();
gumballMachine.turnCrank();
console.log(gumballMachine.toString());
console.log('-----------------------');
gumballMachine.insertQuarter();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();

console.log(gumballMachine.toString());
相關文章
相關標籤/搜索