Why do Woocommerce templates use hooks rather than get_template_part

I’m not familiar with Woocommerce, but in short, get_template_part() only look for template parts in parent and child themes, not in plugins.

If you look at the source code, get_template_part() uses locate_template which have the following source code (which is where the actual template part is searched for)

function locate_template($template_names, $load = false, $require_once = true ) {
    $located = '';
    foreach ( (array) $template_names as $template_name ) {
        if ( !$template_name )
            continue;
        if ( file_exists(STYLESHEETPATH . "https://wordpress.stackexchange.com/" . $template_name)) {
            $located = STYLESHEETPATH . "https://wordpress.stackexchange.com/" . $template_name;
            break;
        } elseif ( file_exists(TEMPLATEPATH . "https://wordpress.stackexchange.com/" . $template_name) ) {
            $located = TEMPLATEPATH . "https://wordpress.stackexchange.com/" . $template_name;
            break;
        }
    }

    if ( $load && '' != $located )
        load_template( $located, $require_once );

    return $located;
}

As you can see, locate_template only look for templates in parent and child themes

That is why you cannot use get_template_part() in a plugin or use it to call template parts into a theme from a plugin.

EDIT from comments from @MarkKaplun

Apart from just the general way in which get_template_part() works in retrieving template parts, Mark has also pointed out a valid point in comments about the use of Woocommerce

I would say it differently – since WC is a plugin it can not have any assumptions about which themes are using it and what parts do they have without limiting its adoption, and WC is meant to work with any theme.