Hay muchas respuestas excelentes aquí, pero a menudo encuentro que usar AMBAS interfaces y clases abstractas es la mejor ruta. Considere este ejemplo artificial:
Eres desarrollador de software en un banco de inversión y necesitas crear un sistema que coloque pedidos en un mercado. Su interfaz de captura la idea más general de lo que un sistema de comercio hace ,
1) Trading system places orders
2) Trading system receives acknowledgements
y se puede capturar en una interfaz, ITradeSystem
public interface ITradeSystem{
public void placeOrder(IOrder order);
public void ackOrder(IOrder order);
}
Ahora los ingenieros que trabajan en el mostrador de ventas y en otras líneas comerciales pueden comenzar a interactuar con su sistema para agregar la funcionalidad de colocación de pedidos a sus aplicaciones existentes. ¡Y aún no has comenzado a construir! Este es el poder de las interfaces.
Así que continúe y construya el sistema para los comerciantes de acciones ; ¡Han escuchado que su sistema tiene una función para encontrar acciones baratas y están ansiosos por probarlo! Captura este comportamiento en un método llamado findGoodDeals()
, pero también se da cuenta de que hay muchas cosas complicadas que están involucradas en la conexión a los mercados. Por ejemplo, tienes que abrir un 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);
}
Las implementaciones concretas van a tener muchos de estos métodos desordenados como connectToMarket()
, pero findGoodDeals()
es lo único que realmente les importa a los traders.
Aquí es donde entran en juego las clases abstractas. Su jefe le informa que los comerciantes de divisas también quieren utilizar su sistema. Y al observar los mercados de divisas, se ve que las tuberías son casi idénticas a las de los mercados de valores. De hecho, connectToMarket()
se puede reutilizar literalmente para conectarse a los mercados de divisas. Sin embargo, findGoodDeals()
es un concepto muy diferente en el ámbito de las divisas. Entonces, antes de pasar el código base al chico mago de las divisas al otro lado del océano, primero refactoriza en unabstract
clase, dejando sin findGoodDeals()
implementar
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>
}
Su sistema de negociación de acciones implementa findGoodDeals()
como ya lo ha definido,
public class StockTradeSystem extends ABCTradeSystem{
public void findGoodDeals();
deals = <apply magic wizardry>
System.out.println("The best stocks to buy are: " + deals);
}
pero ahora el genio FX puede construir su sistema simplemente proporcionando una implementación de findGoodDeals()
para las divisas; ¡no tiene que volver a implementar las conexiones de socket o incluso los métodos de interfaz!
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);
}
La programación en una interfaz es poderosa, pero las aplicaciones similares a menudo vuelven a implementar métodos de formas casi idénticas. El uso de una clase abstracta evita nuevas implementaciones, al tiempo que conserva el poder de la interfaz.
Nota: uno puede preguntarse por qué findGreatDeals()
no forma parte de la interfaz. Recuerde, la interfaz define los componentes más generales de un sistema comercial. Otro ingeniero puede desarrollar un sistema de comercio COMPLETAMENTE DIFERENTE, en el que no les importa encontrar buenas ofertas. La interfaz garantiza que la mesa de ventas también pueda interactuar con su sistema, por lo que es preferible no enredar su interfaz con conceptos de aplicación como "grandes ofertas".