这里有很多很好的答案,但我经常发现同时使用接口和抽象类是最好的方法。 考虑这个人为的例子:
您是一家投资银行的软件开发人员,需要构建一个向市场下订单的系统。您的界面捕捉了交易系统功能的最一般概念,
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()
不是界面的一部分。请记住,接口定义了交易系统中最通用的组件。另一位工程师可能会开发一个完全不同的交易系统,他们并不关心找到好的交易。该界面保证了销售台也可以与他们的系统进行交互,因此最好不要将您的界面与“优惠”之类的应用程序概念纠缠在一起。