Suppose you have a List<Elements> in memory and a List<Files>, each of which is a serialized representation of List<Elements>
The goal is to perform the same algorithm against each of the elements.
Lets say the job is to count elements
int i = 0;
for (Element e : list) {
++i;
}
for (File f : directory()) {
for (Element e : listWeSomehowGetFromTheFile) {
++i;
}
}
Can this be further abstracted somehow? Essentially, algorithm is identical (++i). Is there a way to clean this up?
I certainly can have it’s own class Counter(List<Element>), that has count () method that runs the algo on the list. This way we can:
i+=Counter.count(list);
for (File f : directory()) {
i+=Counter.count(listWeSomehowGetFromTheFile);
}
But even this seems like it can be improved.
For the purposes of this example, lets assume that all operations (a bunch of them) will be performed on list in memory and a list coming from the same files in same directories. The only thing that would change is the algo.
What pattern would fit best to handle something like this?
The Visitor Pattern is quite popular when you want to do something to each item in a collection.
The visitor pattern is also good because it allows you to expand the calculations you can perform without rewriting the class on which visitors operate.
If you don’t need to follow a formal pattern exactly,
1) define an interface like
Operationwith a methodcalculatethat takes an element and operates.2) You calculation is an implementation of
Operation.3) Loop over your elements, passing the elements to your operation implementation.
If the results of calculate are cumulative (depend on previous calculate invocations against other elements), you can modify
calculateto take an object that contains the state of the calculation, and then whencalculateis fired against an element, you update the state. You keep passing the same state object to every calculate invocation.As an outline (this wont compile):