简体   繁体   中英

state design pattern

I am trying to implement the state pattern but the problem is, that I am not changing the states and when I use a test class it is using the concrete class that has a relationship with the interface.

For example in the fire and move methods in the state classes are not working and returning the result of the Railgun.

Here is the code:

public interface RailgunState 
{

    public String fire(Point p, int rounds);
    public String move(Point p);
}

public class Railgun 
{
    /**
     * @param ammo repersent the current ammonitions.
     */
     int ammo = 0;
     /**
     * @param MAX_AMMO repersent the maximum ammonitions.
     */
      public static int MAX_AMMO = 10;
    int test = 10;
    /**
     *@param position represent the possition of the state 
     */
    Point position;
    Point point;
    //ask mark
    int x = 0;
    int y = 0;
    int result = 6;
    /**
     * @param damagedState represent an object of DamagedState
     */
    RailgunState damagedState ;
    RailgunState needAmmoState ;
    RailgunState normalState ;
     /**
     * @param state represent the state of the RailGun
     */
    RailgunState state; 

    Railgun()
    {
        damagedState = new DamagedState();
        needAmmoState = new NeedAmmoState();
        normalState = new NormalState();
        state = normalState;
    }
    /** fire().
     * @param p is the coordinates of the target
     * @param rounds number of rounds HQ has requested
     * @return success/ partial success/ failure
     */
    public String fire(Point p, int rounds)
    {
         return "Fire order: Success 6/6";
    }

    /**  move(). success or failure only the string
     * @param p is the destination
     * @return success or failure when a railgun can move to the destination
     */
    public String move(Point p)
    {
        position = p;
        return  "Move order: Success" ; 
    }

    /**getPosition().
     * @return the possstion of the point 
     */
    public Point getPosition()
    {             
        return position ;
    }

    void setPosition(Point position)
    {
        this.position = position;
    }

     public RailgunState getState()
    {
        return state;
    }

    void setAmmo(int ammo) 
    {
        this.ammo = ammo;
    }

    public Point getPoint() {
        return point;
    }

    public RailgunState getDamagedState() {
        return damagedState;
    }

    public RailgunState getNeedAmmoState() {
        return needAmmoState;
    }

    public RailgunState getNormalState() {
        return normalState;
    }

    int getAmmo()
    {
        return MAX_AMMO;
    }

    void setState(RailgunState state)
    {
         this.state = state;
    }
    void setState(NeedAmmoState needAmmoState)
    {
        this.state = needAmmoState;
    }

    void setState(NormalState normal)
    {
        this.state = normalState;
    }
        void setState(DamagedState damagedState)
    {
        this.state = damagedState;
    }
}


public class NormalState implements RailgunState {

    Railgun railgun;    
    static int MAX_AMMO = 10;
    int result = 6;

    NormalState()
    {
    }
    @Override
    public String fire(Point p, int rounds) 
    {
        MAX_AMMO -= rounds;
        if((MAX_AMMO >= 0) && (rounds == result))
        {
            NeedAmmoState needAmmo = new NeedAmmoState();
            System.out.println("Seccuees: " + MAX_AMMO);
            NormalState state = new NormalState();
            railgun.setState(state);
            return "Fire order: Success 6/6";
        }
        else if((MAX_AMMO < 0) && (MAX_AMMO != -result))
        {
              System.out.println("Partial: " + MAX_AMMO);
              Railgun.MAX_AMMO = 0;
              System.out.println("Partial: " + MAX_AMMO);
              NeedAmmoState needAmmo = new NeedAmmoState();
              railgun.setState(needAmmo);
              return "Fire order: Partial success 4/6";
        }

        else 
        {
             System.out.println("Fail: " + MAX_AMMO);
             DamagedState damaged = new DamagedState();
             railgun.setState(damaged);
             return "Fire order: Failure 0/6";
        }
    }

    @Override
    public String move(Point p)
    {
        return p + "";
    }

    /**getPosition().
     * @return the possstion of the point 
     */
    public Point getPosition()
    {             
        return railgun.getPosition();
    }
}


public class NeedAmmoState implements RailgunState
{
    Point position;
    Railgun railgun;
    NeedAmmoState()
    {
    }

    @Override
    public String fire(Point p, int rounds)
    {
          return "Fire order: Failed 0/4";
    }

    @Override
    public String move(Point p)
    {
        railgun = new Railgun();
         railgun.move(p);
        position = p;
        return  "Move order: Success" ; 
    }

    void setPosition(Point position)
    {
        this.position = position;
    }
    int getAmmo()
    {
        return Railgun.MAX_AMMO;
    }

    /**getPosition().
     * @return the possstion of the point 
     */
    public Point getPosition()
    {             
        int x = 320;
        int y = 43;
        Point p = new Point(x,y);
        return p;
    }
}


public class NormalStateTest {

    /**
     * Test of fire method, of class NormalState.
     */
    @Test
    public void testFire() {
        final Railgun railgun = new Railgun();
        railgun.setState(new NormalState());
        final int numRounds = 6;
        final int x = 100;
        final int y = 340;

        // This fire mission should be completely successful
        String actualResult = railgun.fire(new Point(x, y), numRounds);
        String expectedResult = "Fire order: Success 6/6";
        //System.out.println(actualResult);
        assertEquals(expectedResult, actualResult);

        // This fire mission should be partially successful
        actualResult = railgun.fire(new Point(x, y), numRounds);
        //System.out.println(actualResult);
        expectedResult = "Fire order: Partial success 4/6";
        assertEquals(expectedResult, actualResult);

        // This fire mission should fail
        actualResult = railgun.fire(new Point(x, y), numRounds);
        //System.out.println(actualResult);
        expectedResult = "Fire order: Failure 0/6";
        assertEquals(expectedResult, actualResult);

        // Check state change to NeedAmmo state
        assertEquals(railgun.getState().getClass(), NeedAmmoState.class); 
    }

    /**
     * Test of move method, of class NormalState. Should always succeed.
     */
    @Test
    public void testMove() {
        final Railgun railgun = new Railgun();
        final int x = 129;
        final int y = 444;
        final String actualResult = railgun.move(new Point(x, y));
        final String expectedResult = "Move order: Success";
        System.out.println(actualResult);
        assertEquals(new Point(x, y), railgun.getPosition());
        assertEquals(expectedResult, actualResult);
    }
}

So the problem is that when testing in NormalStateTest.java for example, the result of the classes like NormalState and NeedAmmoSate are returning the values from the Railgun in the methods fire and move.

If you want the RailGun.fire() method delegate to the current state fire() method, then do so. In your code, it returns a hard-coded string and doesn't use the state at all.

Change

public String fire(Point p, int rounds) {
     return "Fire order: Success 6/6";
}

to

public String fire(Point p, int rounds) {
     return state.fire(p, rounds);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM