I have a data structure which has an add function. When the user instantiates a new data structure object, she can specify an algorithm which will be executed each time the add function is called and alters the newly inserted value based on the previous values in the data structure. The algorithm needs to have access to all the data in the data structure
This is not a good idea and besides makes not really sense.
If I get you correctly, you want to create an object which contains some elements e1, e2, e3, .... At a given point in time, you want to do a transformation of the elements so far. At a later point, you want to do another transformation on the collection as a whole.
There is no need to do a transformation in between, since it makes no difference whether the collection stores the values plain vanilla or transformed. At a given point, you need to read or change the transformed values: this is the right point to do a transformation of the colletion (so far) as a whole.
If that is, what you want, this would be a perfect use-case for the visitor pattern:
In case, you have have Python at hand or do not mind installing it, here is a nice example how to set up the visitor pattern
#!/usr/bin/env python3
class Container:
def __init__(self, values):
self._values = values
def transform(self, transformator):
self._values = transformator.transform(self._values)
def accept(self, visitor):
visitor.visit(self)
class Visitor:
pass
class Transformator(Visitor):
pass
class DoublingVisitor(Transformator):
def visit(self, container):
container.transform(self)
def transform(self, values):
return list(map(lambda x: 2*x, values))
def main():
container = Container([1, 2, 3])
doublingVisitor = DoublingVisitor()
container.accept(doublingVisitor)
print(container._values)
if __name__ == '__main__':
main()
Anyways, the python code is easy to understand. The point is, you need one class which I called (lacking of a better name) Container
, which accepts
a Visitor. On the other hand, you need an object derived from Visitor
, which holds as a Transformator
the algorithm (which was the term you used). The Visitor
needs one method visit
, which has one parameter (the object, which it visits). That is the whole magic.
While visiting, the visitor calls the transform method
on the object to visit, which in turn receives the Visitor
/ Transformator
who implements a transform
method. That's it.
Every time, you want to do something with your collection, you could accept another Visitor
.