Refactoring for maintainability

A few steps are needed in order to refactor CardReader:

  1. Define a single protocol for all the states
  2. Extract all states as structs or classes
  3. Implement the logic and transition inside each state object, instead of the context
  4. Refactor the context, in our case CardReader, to leverage those states

First, we need to define a single protocol. This protocol abstracts all the different states, and exposes at least one method that lets an external object perform the work in the said state. This method takes the context (CardReader) as a parameter, in order to perform the transitions.