Пример из реальной жизни. У меня есть система, которая работает с несколькими системами оплаты. При этом в некотором месте я не знаю, какая именно система мне понадобится, я это определяю динамически и создаю класс плательщика и работаю с ним дальше.
IPayer payer = this.getPayer((String) payments.get(i).getSystemCode());
payer.processPayment(payments.get(i));
Во-первых, чисто синтаксически это невозможно сделать без интерфейсов. Во-вторых, я в этом месте вообще не думаю, о том, что там кто платит и по какой механике, и при этом абсолютно уверен, что всё отработает правильно, потому что все плательщики наследуют один интерфейс и отдают данные по одному принципу. Это как если вы покупаете зарядку на microUSB (к примеру) и точно знаете, что она подойдёт к вашему телефону.