Há muitas respostas boas aqui, mas geralmente acho que usar AMBAS as interfaces e classes abstratas é o melhor caminho. Considere este exemplo inventado:
Você é um desenvolvedor de software em um banco de investimento e precisa construir um sistema que coloque pedidos em um mercado. Sua interface captura a ideia mais geral do que um sistema de negociação faz ,
1) Trading system places orders
2) Trading system receives acknowledgements
e pode ser capturado em uma interface, ITradeSystem
public interface ITradeSystem{
public void placeOrder(IOrder order);
public void ackOrder(IOrder order);
}
Agora, os engenheiros que trabalham no balcão de vendas e em outras linhas de negócios podem começar a interagir com seu sistema para adicionar a funcionalidade de colocação de pedidos aos aplicativos existentes. E você ainda nem começou a construir! Este é o poder das interfaces.
Então você vai em frente e constrói o sistema para os corretores de ações ; eles ouviram dizer que seu sistema possui um recurso para localizar ações baratas e estão ansiosos para experimentá-lo! Você captura esse comportamento em um método chamado findGoodDeals(), mas também percebe que há um monte de coisas complicadas envolvidas na conexão com os mercados. Por exemplo, você deve abrir um SocketChannel,
public class StockTradeSystem implements ITradeSystem{
@Override
public void placeOrder(IOrder order);
getMarket().place(order);
@Override
public void ackOrder(IOrder order);
System.out.println("Order received" + order);
private void connectToMarket();
SocketChannel sock = Socket.open();
sock.bind(marketAddress);
<LOTS MORE MESSY CODE>
}
public void findGoodDeals();
deals = <apply magic wizardry>
System.out.println("The best stocks to buy are: " + deals);
}
As implementações concretas vão ter muitos desses métodos confusos, como connectToMarket(), mas findGoodDeals()é tudo com que os comerciantes realmente se preocupam.
Agora é aqui que as classes abstratas entram em jogo. Seu chefe informa que os negociantes de moeda também desejam usar seu sistema. E olhando para os mercados de câmbio, você vê que o encanamento é quase idêntico ao dos mercados de ações. Na verdade, connectToMarket()podem ser reutilizados literalmente para se conectar aos mercados de câmbio. No entanto, findGoodDeals()é um conceito muito diferente na arena monetária. Portanto, antes de passar a base de código para o garoto mago do câmbio do outro lado do oceano, você primeiro refatora em uma abstractclasse, deixando não findGoodDeals()implementado
public abstract class ABCTradeSystem implements ITradeSystem{
public abstract void findGoodDeals();
@Override
public void placeOrder(IOrder order);
getMarket().place(order);
@Override
public void ackOrder(IOrder order);
System.out.println("Order received" + order);
private void connectToMarket();
SocketChannel sock = Socket.open();
sock.bind(marketAddress);
<LOTS MORE MESSY CODE>
}
Seu sistema de negociação de ações implementa findGoodDeals()como você já definiu,
public class StockTradeSystem extends ABCTradeSystem{
public void findGoodDeals();
deals = <apply magic wizardry>
System.out.println("The best stocks to buy are: " + deals);
}
mas agora o garoto prodígio do FX pode construir seu sistema simplesmente fornecendo uma implementação de findGoodDeals()para moedas; ela não tem que reimplementar as conexões de soquete ou mesmo os métodos de interface!
public class CurrencyTradeSystem extends ABCTradeSystem{
public void findGoodDeals();
ccys = <Genius stuff to find undervalued currencies>
System.out.println("The best FX spot rates are: " + ccys);
}
A programação para uma interface é poderosa, mas aplicativos semelhantes geralmente reimplementam métodos de maneiras quase idênticas. O uso de uma classe abstrata evita reimplmentações, enquanto preserva o poder da interface.
Nota: pode-se perguntar por que findGreatDeals()não faz parte da interface. Lembre-se de que a interface define os componentes mais gerais de um sistema de negociação. Outro engenheiro pode desenvolver um sistema de negociação COMPLETAMENTE DIFERENTE, onde eles não se importam em encontrar bons negócios. A interface garante que o balcão de vendas também possa interagir com o sistema deles, portanto, é preferível não confundir sua interface com conceitos de aplicativos como "ótimas ofertas".