我想避免使用条件并应用一些技术来使代码更易于维护,并且在使用继承类时可以轻松扩展。
在这个例子中我们有。
MarketOrder和LimitOrder都从基类Order扩展。
TradeServiceImpl,方法为getUnitPrice,用于计算2个订单的交易价格。
此方法有几个条件可为不同类型的订单选择正确的价格。此外,它正在转换为派生类。
这个方法的问题是,如果我想添加5个新订单,我会有7 * 7 = 49 if语句,在其中一些我需要转换为一个派生类,我可能会混淆另一个,这看起来非常容易编写错误的代码,并给我我应该重新设计的气味。
我能得到一些想法吗?
// Domains.
public class Order{
private OrderTypeEnum orderType;
// can be buy or sell
public OrderTypeEnum getOrderType() {
return orderType;
}
public void setOrderType(OrderTypeEnum orderType) {
this.orderType = orderType;
}
}
public class LimitOrder extends Order{
private Long unitPrice;
public Long getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(Long unitPrice) {
this.unitPrice = unitPrice;
}
}
public class MarketOrder extends Order{
}
// Service.
public class TradeServiceImpl implements TradeService{
private TradeRepository tradeRepository;
public Long getUnitPrice(Order buyOrder, Order sellOrder){
if(buyOrder instanceof MarketOrder && sellOrder instanceof MarketOrder){
return tradeRepository.getLastPrice();
}
if(buyOrder instanceof MarketOrder && sellOrder instanceof LimitOrder){
return ((LimitOrder)sellOrder).getUnitPrice();
}
if(buyOrder instanceof LimitOrder && sellOrder instanceof MarketOrder){
return ((LimitOrder)buyOrder).getUnitPrice();
}
if(buyOrder instanceof LimitOrder && sellOrder instanceof LimitOrder){
return ((LimitOrder)buyOrder).getUnitPrice() + ((LimitOrder)sellOrder).getUnitPrice() /2;
}
return 0L;
}
}
答案 0 :(得分:3)
首先,有两种情况可以合并为一种:当订单不同时:
if(buyOrder instanceof MarketOrder && sellOrder instanceof LimitOrder){
return ((LimitOrder)sellOrder).getUnitPrice();
}
if(buyOrder instanceof LimitOrder && sellOrder instanceof MarketOrder){
return ((LimitOrder)buyOrder).getUnitPrice();
}
要:
if(!buyOrder.getClass().equals(LimitOrder.getClass())){
return ((LimitOrder)sellOrder).getUnitPrice();
}
另一方面,您可以使用订单类作为包含功能对象的地图的索引。这样,您只需在此地图中添加元素即可扩展您的功能。
您可以使用实现如下界面的匿名内部类来封装计算算法:
public interface IFunction {
public Long execute(Order oA, Order oB);
}
并决定使用订单类执行访问此地图的行为:
Map<Class, Map<Class, IFunction>> opClass2calcAlgorithm = new HashMap();
IFunction market_market = new IFunction() {
@Override
public Long execute(Order a, Order b) {
return tradeRepository.getLastPrice();
}
};
IFunction market_limit = new IFunction() {
@Override
public Long execute(Order a, Order b) {
return ((LimitOrder)a).getUnitPrice();
}
};
Map<Class, IFunction> marketMap = new HashMap();
marketMap.put(MarketOrder.class, market_market);
marketMap.put(LimitOrder.class, market_limit);
opClass2calcAlgorithm.put(marketMap);
最后,您的getUnitPrice
方法可以像这样实现:
public Long getUnitPrice(Order buyOrder, Order sellOrder){
long ret = 0L;
Map<Class, IFunction> firstLevel = opClass2calcAlgorithm.get(buyOrder.getClass());
if(firstLevel == null) return ret;
IFunction calcAlg = firstLevel.get(sellOrder.getClass());
if(calcAlg == null) return ret;
ret = calcAlg.execute(buyOrder, sellOrder);
return ret;
}
答案 1 :(得分:0)
首先,在获得价格之前,您不需要将buyOrder / sellOrder投射到特定的类类型(因为多态性)。即。
public Long getUnitPrice(Order buyOrder, Order sellOrder){
if(buyOrder instanceof MarketOrder && sellOrder instanceof MarketOrder){
return tradeRepository.getLastPrice();
}
if(buyOrder instanceof MarketOrder && sellOrder instanceof LimitOrder){
return sellOrder.getUnitPrice();
}
if(buyOrder instanceof LimitOrder && sellOrder instanceof MarketOrder){
return buyOrder.getUnitPrice();
}
if(buyOrder instanceof LimitOrder && sellOrder instanceof LimitOrder){
return (buyOrder.getUnitPrice() + sellOrder.getUnitPrice()) /2;
}
return 0L;
}
其次,对于计算逻辑,您可以使用工厂模式根据订单类型返回适当的计算器。不幸的是,我没有足够的关于您的代码的上下文来建议确切的代码。我建议你在线搜索工厂模式和策略模式。他们应该帮助您为代码设计更好的策略。