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 abstract
classe, 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".