1

I need to implement two similar processes which basicaly do the same logic but a few parameters/methods may differ. I'm wondering if it would be a good practice to extract the main logic to a parent class and specify a result of a few methods to child classes. Something like:

abstract class Parent{

protected CommonDao commonDao;

protected String specStatus;

protected abstract int getDbResult();

public Parent(CommonDao commonDao){
    this.commonDao = commonDao;
}

public String mainLogic(){
    if(commonMethod()){
    //..
    }
    int specDbResult = getDbResult();
    //some logic here

    return specStatus;
}

private boolean commonMethod(){ 
//.. 
return true;
}

}

@Service
public Child1 extends Parent(){

  @Autowired
  public Child1(CommonDao commonDao){
     super(commonDao);
     super.specStatus = specStatus1;
  }

  @Override
  protected String getDbResult(){
      commonDao.getResult1();
  }

}

@Service
public Child2 extends Parent(){

  @Autowired
  public Child2(CommonDao commonDao){
     super(commonDao);
     super.specStatus = specStatus2;
  }

  @Override
  protected String getDbResult(){
      commonDao.getResult2();
  }

}

If it doesn't seem to be a clean code, what solution would you recommend in such case? Thanks in advance

adolzi
  • 671
  • 2
  • 7
  • 15
  • https://javapapers.com/design-patterns/template-method-design-pattern/ you can look into it, – bananas Jan 31 '20 at 08:52
  • Thanks for the comment. It looks similar to my code, it's also some kind of algorithm what steps need to be done, but in my code most of the logic should be the same between children (so pasted to parent class). Difference is basicaly on a few parameters, and calling another dao method. – adolzi Jan 31 '20 at 09:24

1 Answers1

0

Using Dependency Injection, composition seems clearly a better approach that inheritance

And dao as an attribute is not enough for a parent child relationship

Please make sure you have understood Item 16 of Effective Java, as any programmer might http://thefinestartist.com/effective-java/16

EDITED as requested:

@Service
public class NotAChild{

@Autowired
CommonOps1 commonOps1;

@Autowired
CommonOps2 commonOps2;

private boolean commonMethod(){ 
int result1 = commonOps1.getDbResult(); 
int result2 = commonOps2.getDbResult(); 
....
return result1 + result2;
}
}

@Component
public class CommonOpS1{

@Autowired
CommonDao commonDao;

protected String getDbResult(){
      commonDao.getResult1();
}

}

@Component
public class CommonOpS2{

@Autowired
CommonDao commonDao;

protected String getDbResult(){
      commonDao.getResult2();
}

}

All other NotAChildN objects can use the common methods of CommonOps.

So, you won't use inheritance

inquirymind
  • 135
  • 1
  • 11
  • Could you please elaborate more? I don't see how to rewrite my code in this case. – adolzi Jan 31 '20 at 10:17
  • So from what I assume commonMethod() would be my alorithm. But when having many CommonOpS what about autowiring? – adolzi Jan 31 '20 at 10:41
  • The framework creates your Component. Autowiring hands it to your service. If you have many Components, you autowire the ones you need for the Service. I have enhanced the example – inquirymind Jan 31 '20 at 11:01
  • This is not exactly what I was looking for - I do need to combine results, I need to use one and another time to use second. Template method seems to be a better solution here I think – adolzi Jan 31 '20 at 11:08
  • result1 + result2 looks like combining results to me. Why it is not? – inquirymind Jan 31 '20 at 11:15
  • Apologies, typo, I meant 'do not' – adolzi Jan 31 '20 at 11:16
  • If you actually need to implement the template design pattern, just implement an abstract class and let CommonOpsN extend it. Then your Service is the client. Leave the Autowireds within the Components and pass the beans as parameters of the commons methods to the abstract parent class. – inquirymind Jan 31 '20 at 18:33