Clear[f]
f[a_] := a
f[{a_, b_}] := a
Downvalues of a symbol hold the patterns used for its evaluation.
dv = DownValues[f]
{HoldPattern[f[{a_, b_}]] :> a, HoldPattern[f[a_]] :> a}
Downvalues are searched in normal order, first to last. Therefore,
{f[{2, 3}], f[42]}
{2, 42}
Downvalues can be reordered to get a different evaluation order.
DownValues[f] = Reverse @ dv
{HoldPattern[f[a_]] :> a, HoldPattern[f[{a_, b_}]] :> a}
{f[{2, 3}], f[42]}
{{2, 3}, 42}
If a new rule is added to downvalues, it is inserted into the list of downvalues according to Mathematica's idea of specificity, but ordering of the downvalues is not otherwised changed.
f[42] := 0
DownValues[f]
{HoldPattern[f[42]] :> 0, HoldPattern[f[a_]] :> a, HoldPattern[f[{a_, b_}]] :> a}
{f[{2, 3}], f[42], f[3]}
{{2, 3}, 0, 3}
There are many situations in Mathematica where overloading function definitions in the manner you describe is extremely useful. So don't fear overloading function definitions, make it one more tool in your programming toolbox.