Jest tu wiele świetnych odpowiedzi, ale często uważam, że używanie OBU interfejsów i klas abstrakcyjnych jest najlepszą drogą. Rozważmy ten wymyślony przykład:
Jesteś programistą w banku inwestycyjnym i musisz zbudować system, który będzie składał zamówienia na rynek. Twój interfejs zawiera najbardziej ogólne pojęcie o tym, co robi system transakcyjny ,
1) Trading system places orders
2) Trading system receives acknowledgements
i można je przechwycić w interfejsie, ITradeSystem
public interface ITradeSystem{
public void placeOrder(IOrder order);
public void ackOrder(IOrder order);
}
Teraz inżynierowie pracujący w dziale sprzedaży i na innych liniach biznesowych mogą zacząć łączyć się z systemem, aby dodać funkcjonalność składania zamówień do swoich istniejących aplikacji. I jeszcze nawet nie zacząłeś budować! To jest siła interfejsów.
Więc idź dalej i zbuduj system dla inwestorów giełdowych ; słyszeli, że Twój system ma funkcję wyszukiwania tanich akcji i bardzo chętnie ją wypróbowują! Ujmujesz to zachowanie za pomocą metody zwanej findGoodDeals()
, ale zdajesz sobie sprawę, że jest wiele niechlujnych rzeczy związanych z łączeniem się z rynkami. Na przykład musisz otworzyć 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);
}
Konkretne implementacje będą miały wiele takich niechlujnych metod connectToMarket()
, ale na tym findGoodDeals()
wszystkim zależy traderom.
Teraz w grę wchodzą klasy abstrakcyjne. Twój szef poinformuje Cię, że traderzy walutowi również chcą korzystać z Twojego systemu. Patrząc na rynki walutowe, widać, że kanalizacja jest prawie identyczna jak na giełdach. W rzeczywistości connectToMarket()
może być ponownie użyty dosłownie do łączenia się z rynkami walutowymi. Jednak findGoodDeals()
na arenie walutowej jest to zupełnie inna koncepcja. Zanim więc przekażesz kod źródłowy czarodziejowi zajmującemu się handlem walutami po drugiej stronie oceanu, najpierw zmienisz kod na abstract
klasę, pozostawiając findGoodDeals()
nieskomplikowaną
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>
}
Twój system handlu akcjami wdraża się findGoodDeals()
tak, jak już zdefiniowałeś,
public class StockTradeSystem extends ABCTradeSystem{
public void findGoodDeals();
deals = <apply magic wizardry>
System.out.println("The best stocks to buy are: " + deals);
}
ale teraz dzieciak, który specjalizuje się w FX, może zbudować swój system, po prostu dostarczając implementację findGoodDeals()
dla walut; nie musi ponownie implementować połączeń gniazd ani nawet metod interfejsu!
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);
}
Programowanie w interfejsie jest potężne, ale podobne aplikacje często ponownie implementują metody w prawie identyczny sposób. Użycie klasy abstrakcyjnej pozwala uniknąć powtórzeń, przy jednoczesnym zachowaniu mocy interfejsu.
Uwaga: można się zastanawiać, dlaczego findGreatDeals()
nie jest częścią interfejsu. Pamiętaj, że interfejs definiuje najbardziej ogólne elementy systemu handlowego. Inny inżynier może opracować ZUPEŁNIE RÓŻNY system transakcyjny, w którym nie zależy mu na znalezieniu dobrych transakcji. Interfejs gwarantuje, że dział sprzedaży może również połączyć się ze swoim systemem, dlatego lepiej nie mieszać interfejsu z koncepcjami aplikacji, takimi jak „świetne okazje”.