我最近正在开发一个代码库,它在整个代码中使用了大量的instanceof检查,我想知道是否有更好的方法来重构它。
作为一个例子,有一个AbstractTender类,它有几个子类,CreditDebitTender,CheckTender,GiftCardTender,StoreCreditTender等。这些类中的每一个都添加了几个字段,方法和它自己的逻辑。这导致对代码进行检查,如下所示。
有没有更好的方法来避免代码库中的所有实例检查,因为在某些情况下,超类和子类IE之间存在显着差异,有很多非常不同的字段/方法?正如示例maskedCardNumber和authCode仅特定于信用借记投标,而micr仅针对检查投标。
if (tender instanceof CreditDebitTenderIfc) {
// insert tender into credit debit tender table
}
if (tender instanceof CheckTenderIfc) {
// insert tender into check tender table
}
if (tender instance of GiftCardTenderIfc) {
// inser tender into gift card tender table
}
// etc
仅供参考:这是一个非常古老的代码库,原始产品已超过10年。
答案 0 :(得分:1)
我可以通过两种方式思考:
在名为AbstractTender
的{{1}}中定义一个抽象方法。每个子类都必须实现信息应该如何存储在数据库中。
如果save
和子类是实体类而不能拥有存储库逻辑,并且如果使用Java 8,则可以使用AbstractTender
,其中地图的每个值都关注如何存储Map<Class, Consumer<AbstractTender>>
的实例。您可以使用实例的类来查找特定元素。
简要示例:
AbstractTender
然后您的Map<Class, Consumer<AbstractTender>> mapTenderStoreFunc = new HashMap<>();
mapTenderStoreFunc.put(CreditDebitTenderIfc.class, tender -> {
CreditDebitTenderIfc cdTender = (CreditDebitTenderIfc)tender;
//logic goes here...
});
mapTenderStoreFunc.put(CheckTenderIfc.class, tender -> {
CheckTenderIfccdTender ctifc = (CheckTenderIfc)tender;
//logic goes here...
});
//and on...
方法会像这样使用地图:
save
这种方法的缺点是,如果团队中的某个人忘记为子类添加正确的映射,那么您就会陷入困境。
2的类似方法,但是如果您使用Java 7或更早版本,而不是public void save(AbstractTender tender) {
Consumer<AbstractTender> saveOperation = mapTenderStoreFunc.get(tender.getClass());
if (saveOperation != null) {
saveOperation.accept(tender);
} else {
//maybe throw an exception
//or log a warning, error or something to notice!
}
}
,您可以定义自己的界面并用匿名类填充它:
Consumer<AbstractTender>
答案 1 :(得分:1)
根据代码确定已经创建了招标对象。 该对象可以是任何一个子类对象。 所以可以使用回调行为。
public abstract class AbstractTender{
abstract void insert();
}
public class CreditDebitTenderIfc extends AbstractTender{
@Override
public void insert(){
// insert tender into credit debit tender table
}
}
class Main{
public void doOperation(AbstractTender tender){
tender.insert();
}
}
由于你已经有了招标对象,只需打电话 tender.insert(); 它将调用适当的子类方法。