这里有很多很棒的答案,但是我经常发现使用BOTH接口和抽象类是最好的方法。 考虑这个人为的例子:
您是一家投资银行的软件开发人员,需要构建一个将订单投放到市场的系统。您的界面捕获了有关交易系统功能的最一般的想法,
1) Trading system places orders
2) Trading system receives acknowledgements
并可以在界面中捕获 ITradeSystem
public interface ITradeSystem{
public void placeOrder(IOrder order);
public void ackOrder(IOrder order);
}
现在,在销售台和其他业务部门工作的工程师可以开始与您的系统交互,以将订单下达功能添加到其现有应用程序中。而且您甚至还没有开始构建!这就是界面的力量。
因此,您可以继续建立适用于股票交易员的系统;他们听说您的系统具有查找便宜股票的功能,并且非常渴望尝试!您通过一种称为的方法来捕获这种行为findGoodDeals()
,但同时也意识到在连接市场时涉及到很多混乱的事情。例如,你要打开一个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);
}
具体的实现将有很多类似这样的凌乱方法connectToMarket()
,但这findGoodDeals()
是所有交易者真正关心的。
现在,这里是抽象类起作用的地方。 您的老板告诉您,货币交易员也希望使用您的系统。纵观货币市场,您会发现管道几乎与股票市场相同。实际上,connectToMarket()
可以逐字重复使用以连接到外汇市场。但是,findGoodDeals()
在货币领域是一个截然不同的概念。因此,在将代码库传递给跨洋的外汇智商之前,您首先要重构为一个abstract
类,findGoodDeals()
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>
}
您的股票交易系统会findGoodDeals()
按照您已定义的方式实施,
public class StockTradeSystem extends ABCTradeSystem{
public void findGoodDeals();
deals = <apply magic wizardry>
System.out.println("The best stocks to buy are: " + deals);
}
但是现在,外汇小子可以通过简单地提供findGoodDeals()
货币实现来构建自己的系统。她不必重新实现套接字连接,甚至不必重新实现接口方法!
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);
}
对接口进行编程功能强大,但是相似的应用程序通常以几乎相同的方式重新实现方法。使用抽象类可避免重复,同时保留了接口的功能。
注意:有人可能想知道为什么findGreatDeals()
不是界面的一部分。请记住,该接口定义了交易系统的最常规组件。另一位工程师可能会开发一个完全不同的交易系统,而他们并不关心寻找好的交易。该接口保证了销售台也可以与他们的系统接口,因此最好不要将您的接口与诸如“大笔交易”之类的应用程序概念纠缠在一起。