Reputation: 23
I have a class that has one or more input list and it needs to process and update other lists which are scoped outside of the class. What can be a good pattern to use here? I've tried the following two patterns here:
Examples
public class SomeClass {
public void process(List<String> inputList, List<StringContainer> errorContainerList, List<String> validList) {
for (String str : inputList) {
if (someCondition) {
validList.add(str);
} else {
errorContainerList.add(new StringContainer(str, new SomeError()));
}
}
}
}
void someCaller(List<String> inputList) {
List<String> validList = new ArrayList<>();
List<StringContainer> errorContainerList = new ArrayList<>();
SomeClass obj = new SomeClass();
obj.process(inputList, errorContainerList, validList);
// Similarly,
validList.remove(...);
errorContainerList.add(...);
}
public interface StringErrorHandler {
void handle(String str, SomeError error);
}
public interface ValidInputHandler {
void handle(String str);
}
public class SomeClass {
public void process(List<String> inputList, StringErrorHandler errorHandler, ValidInputHandler validInputHandler) {
for (String str : inputList) {
if (someCondition) {
validInputHandler.handle(str);
} else {
errorHandler.handle(str, new SomeError());
}
}
}
}
void someCaller(List<String> inputList) {
List<String> validList = new ArrayList<>();
List<StringContainer> errorContainerList = new ArrayList<>();
SomeClass obj = new SomeClass();
obj.process(inputList, new StringErrorHandler() {
@Override
public void handle(String str, SomeError error) {
errorContainerList.add(new StringContainer(str, error));
}
}, new ValidInputHandler() {
@Override
public void handle(String str) {
validList.add(str);
}
});
// Similarly,
validList.remove(...);
errorContainerList.add(...);
}
Upvotes: 2
Views: 84
Reputation: 661
I would use neither of them. They are both unnescessarily complicated. Let's think what is your actual problem here? If you didn't care for error handling, you'd probably write something like this:
public List<String> process(List<String> inputList) {
List<String> validList = new ArrayList<>();
for (String str : inputList) {
if (someCondition) {
validList.add(str);
}
}
return validList;
}
So the problem is that you can't return two values from a method in java. But to handle that you can add a simple nested class having these 2 values and the client then can easily extract them:
public ProcessResult process(List<String> inputList) {
List<StringContainer> errorContainerList = new ArrayList<>();
List<String> validList = new ArrayList<>();
for (String str : inputList) {
if (someCondition) {
validList.add(str);
} else {
errorContainerList.add(new StringContainer(str, new SomeError()));
}
}
return new ProcessResult(validList, errorContainerList)
}
public static class ProcessResult{
public final List<String> validList;
public final List<StringContainer> errorContainerList;
public ProcessResult(List<String> validList, List<StringContainer> errorContainerList) {
this.validList = validList;
this.errorContainerList = errorContainerList;
}
}
void someCaller(List<String> inputList) {
List<String> validList = new ArrayList<>();
List<StringContainer> errorContainerList = new ArrayList<>();
SomeClass obj = new SomeClass();
ProcessResult pr=obj.process(inputList);
validList.addAll(pr.validList);
errorContainerList.addAll(pr.errorContainerList);
}
This is better for few reasons, but most important are, that there are no side effects to your method and that the result of the method is explicitly returned, which is what we're supposed to do in java
Upvotes: 1