I have the following 2 methods (some codes omitted for brevity) in my Java (Spring) app and I want to reduce duplicated blocks in these methods. At this point, after making some research, some people suggesting Builder Pattern, some of them another similar one Template Method. I also think that, I could simply create 2 separate methods and move each repeated code blocks to these methods.
However, I have no experience about this issue and I would like to ask you first to follow the most proper ways. So, how should I reduce the code duplication in the following 2 methods? I also think to use inheritance, but I am really confused with finding a proper way.
Not: I omitted my code and use a simple code for brevity:
@Override
public MultipartFile exportAaaaa() throws IOException {
// repeated code block I
workbook = new XSSFWorkbook();
sheet = workbook.createSheet(TextBundleUtil.read(TITLE));
rowCount = new AtomicInteger(0);
//
// private block to this method
final Page<Aaaaa> page = aaaaaService.findAll());
// ...
// repeated code block II
outputFile = File.createTempFile(TextBundleUtil.read(TITLE), EXTENSION);
try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
workbook.write(outputStream);
} catch (IOException e) {
LoggingUtils.error("Writing is failed ", e);
}
final FileInputStream input = new FileInputStream(outputFile);
final String fileName = TextBundleUtil.read(TITLE).concat(EXTENSION);
return new MockMultipartFile(fileName,
fileName, CONTENT_TYPE, IOUtils.toByteArray(input));
//
}
@Override
public MultipartFile exportBbbbb() throws IOException {
// repeated code block I
workbook = new XSSFWorkbook();
sheet = workbook.createSheet(TextBundleUtil.read(TITLE));
rowCount = new AtomicInteger(0);
//
// private block to this method
final Page<Bbbbb> page = bbbbbService.findAll());
// ...
// repeated code block II
outputFile = File.createTempFile(TextBundleUtil.read(TITLE), EXTENSION);
try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
workbook.write(outputStream);
} catch (IOException e) {
LoggingUtils.error("Writing is failed ", e);
}
final FileInputStream input = new FileInputStream(outputFile);
final String fileName = TextBundleUtil.read(TITLE).concat(EXTENSION);
return new MockMultipartFile(fileName,
fileName, CONTENT_TYPE, IOUtils.toByteArray(input));
//
}
CodePudding user response:
Without having much information about the actual code, it sounds like the only variable between the two methods is A vs B. The first solution that comes to mind is the use of generics. Have your class take a type parameter, and have subclasses that target specific types. In your code I see the use @Override
so you probably already have a parent class or interface:
public interface Persister<T> {
void save(T t);
}
public class APersister implements Persister<A> {
@Override
public void saveA(A a) {
}
}
public class BPersister implements Persister<B> {
@Override
public void saveB(B a) {
}
}
To avoid duplicate code, you could make the parent type an abstract class and refactor the code to be something like:
abstract class Persister<T> {
public void save(T t) {
System.out.println("Saving " t.getId());
final T t = doSave(t);
log("Saved " t.getId());
}
protected abstract void doSave(T t);
}
Then you'd implement doSave()
specifically for each subclass.
CodePudding user response:
I see here, that the duplicated code is a logging(or console printing). But it is not clear in this example what are aService and bService do? May be they have a different logics inside? As I see they return the different result. But if A.class and B.class are the implementation of one interface, and aService and bService are also implementations of one interface. It could be the one method. Maybe)