Based on your recent edit.
The decorator is not suitable for this, as you might understand. This is due to the fact that what he decides is an addition to one functionality, and not an addition to a whole tree of classes.
Perhaps this can be achieved with strategy. The strategy is algorithmically focused; it allows you to separate the behavioral code (sorry if a little C # slips here and there)
Class example
public class S{ private List<Integer> Samples = new List<Integer>(); public void addSample(int x){ Samples.Add(new Integer(x)); } public void Process(IOp[] operations){ for (Op operation : operations){ Process(operation); } } public void Process(ICollection<IOp> operations){ for (Op operation : operations){ Process(operation); } } public void Process(IOp operation){ operation.Compute(this.Samples); } }
Operations
public interface IOp{ // Interface is optional. Just for flexibility. public void Compute(List<Integer> data); } public class Op<T> implements IOp{ // Generics is also optional. I use this to standardise data type of Result, so that it can be polymorphically accessed. // You can also put in some checks to make sure Result is initialised before it is accessed. public T Result; public void Compute(List<Integer> data); } class ComputeMeanOperation extends Op<double>{ public void Compute(List<Integer> data){ /* sum and divide to get mean */ this.Result = /* ... */ } } class CheckConvergenceOperation extends Op<boolean>{ public void Compute(List<Integer> data){ /* check convergence */ this.Result = /* ... */ } }
Using
public static void main(String args[]){ S s = new S(); s.addSample(1); ComputeMeanOperation op1 = new ComputeMeanOperation(); CheckConvergenceOperation op2 = new CheckConvergenceOperation ();
Pros:
- You can optionally add and remove operations depending on what you need.
- no additional changes to the class of samples.
- The class of the sample is the structure of the whole structure.
- modularity: each op is autonomous. the interface provides only what is required. The general process of interaction with each operator.
- If for some reason you need to do this several times, you can save all op in an array and reuse it in a loop. Much cleaner than calling 4-5 methods and saving results.
Cons / Limitations:
- If your operations require a large amount of data, then you will have to expose this data to your actions, increasing communication (I can edit the message if you need it). In my example, I just passed one list of examples. If necessary, you may need to transfer the entire data structure.
- If you have any operations that depend on the result of another operation, this will not work. (This can be done using Composite instead - a mega-Op, which consists of several Ops, the result of which is passed to the next.)
Hope this meets your requirements :)
source share