Beyond separating each Form into separate classes, another significant change is the introduction of FormStateInterface. In Drupal 7, the $form_state variable that was passed to the various form functions was a simple array. However, in Drupal 8, in addition to getting the values from the previous form actions, the FormStateInterface is used to set form errors. In Drupal 7, if you needed to indicate an error with a form field, you would call the following:
Form_set_error('first_name', t('The first name is invalid'));
In Drupal 8, this looks like this:
$form_state->setErrorByName('first_name', $this->t('The first name is invalid'));
The FormStateInterface has some other nice convenience functions, especially around checking to see whether a form element has data. You can easily check for the existence of a value using FormStateInterface::isValueEmpty as well as pass a default value to FormStateInterface::getValue. Moving to functions to return values does have one side effect that takes some getting used to. Previously, you would get nested values by just traversing the appropriate array in the $form_state array, for example $form_state['values']['nested']['value']. In order to get the same value from the FormStateInterface, you pass an array to getValue, for example $form_state->getValue(array('nested', 'value')).