Using wp_ajax and wp_ajax_nopriv hooks

It depends on what exactly you want to do. If you want to show just a short message, use the same callback for both.

But if you need completely different objects and load different additional files depending on the log-in status, use separate callbacks.

Basic example, probably not a recommended implementation. 🙂

class Ajax_Controller {

    public function __construct( $action ) {

        add_action( "wp_ajax_nopriv_$action", array ( $this, 'logged_out' ) );
        add_action( "wp_ajax_$action",        array ( $this, 'logged_in' ) );
    }

    public function logged_out() {

        require_once __DIR__ . '/Logged_Out_Data_Interface.php';
        require_once __DIR__ . '/Logged_Out_Data.php';
        require_once __DIR__ . '/Logged_Out_View.php';

        $data = new Logged_Out_Data;
        $view = new Logged_Out_View( $data );
        $view->render();
    }

    public function logged_in() {

        require_once __DIR__ . '/Logged_In_Data_Interface.php';
        require_once __DIR__ . '/Logged_In_Data.php';
        require_once __DIR__ . '/Logged_In_View.php';

        $data = new Logged_In_Data;
        $view = new Logged_In_View( $data );
        $view->render();
    }
}

Look at your use case, be pragmatic. When in doubt, compare the performance and the complexity of both approaches.