I think the difference between the first:
minlength="3" maxlength="15" pattern="[a-zA-Z0-9]+"
and the second:
is, that the first solution let the user know, that the amount of characters is incorrect.
But the second solution just tells the user, that the input didn’t match the requested format. So, the first solution gives the user more information on what exactly went wrong.