Skip to main content

State Design Pattern - TypeScript

Rover Coding - Description

Let's write code to simulate a Rover !

Rover has the following attribures and behaviour

  • Attributes:
    • Coordinates (x,y)
    • Facing - North, South, East or West
  • Behaviour
    • Commands to move - Forward, Backward, Left or Right

You are given an initial starting point of the Rover ex: (0,0) and the direction it is facing ex: North.

Rover receives a character array of commands. Ex: ['r', 'l', 'f', 'b' ]

r - Right, l - Left, f - Forward, b - backward,

Implement commands to move the Rover forward/ backward/ right/ left

When the Rover moves, its attribures will change based on the facing the Rover is currently is and the move it is making. Below are some examples.

For ex:

If the Rover is facing North then:

  1. moving Right will change the facing to East but co-ordinates will remain the same
  2. moving Forward will increment the y co-ordinate but Facing will remain the same

First Step

  • Implement the Rover without using any design patterns. This is an important step. Wihout this step, if you directly jump to deisgn pattern then you will not know what problem the design pattern is solving, so do not skip this step.

  • As you start writing the code, you will see that lots of decisions have to me made and the code soon becomes complex to manage.

  • Read some theory about State Design Pattern just to get a high level view of how it can solve the problem. Don't worry if you don't understand it fully.

Applying State Design Pattern

  • Create a Main class, name it as Rover
  • Create an interface called Facing and add four interface methods to move the rover
export interface Facing {
moveForward: Function;
moveBackwards: Function;
moveLeft: Function;
moveRight: Function;
}
  • There are four facings, so create classes for each of the facing.

    • North
    • South
    • East
    • West
  • Each of the above classes will implement the interface Facing

  • We are going to encapsulate the logic of moving Rover inside these objects. Rover will use the interface methods of Facing object. Rover does not need to know which facing it currently is. It just calls the interface methods on its current facing object. Facing object will have a reference to the Rover object so that it can update the currnet facing of the Rover based on the move command.

  • Rover exposes a method to set its facing. Ex: setFacing(<new facing>)

  • Rover also exposes methods to update its co-ordinates.

  • Each Facing object will have an instance of the Rover given to it when the facing object is created, so that current facing of the rover can be changed dynamically by calling setFacing() rover method from within the facing object.

  • Write tests along the way - TDD

Pre-Requisites

  • My GitHub repository: https://github.com/smarigowda/state-design-pattern-rover
  • Node js (ex: v12.16.1)
  • VS Code Editor

Steps

  • Clone the repository
    • git clone git@github.com:smarigowda/state-design-pattern-rover.git
  • Install npm packages
    • npm install
  • Run the tests
    • npm run test

Screen Cast: Running and Debugging Jest test

State Transition Diagram - Facing Objects

Sequence Diagram

Jest Test Run

Code without any Design Pattern