Frage

I have two algorithms that I'm implementing:

  • AlgorithmA which works with Vector values and
  • AlgorithmB which works with Matrix values

What the algorithms have in common:

  • Both are "summation" algorithms that are supplied with the same sequence of inputs. Algorithms vary slightly on whether to account for a particular value or not. They also vary in the computation to be performed per value of the sequence.
  • Both algorithms are referenced by the same object (e.g. an 'Antenna' that uses an algorithm for transmission or receiving).
  • In both cases, I want to be able to serialize the Vector or Matrix result. In addition, I should be able to initialize any of the algorithms with (deserialized) vector/matrix values computed from an earlier generaion.

I first tried implementing the above using the Strategy pattern, but soon I realized that the strategy pattern might not be the best due to the varying types/values. And to further complicate things, my 'Antenna' object could use any of the algorithms in either direction:

class Antenna
{
    private AlgorithmParams _algorithm;
}

class AlgorithmParams
{
     private IAlgorithm _transmit;
     private IAlgorithm _receive;
}   

which I feel that it duplicates the notion of "transmit" and "receive" multiple times (because AlgorithmA, which implements IAlgorithm, itself has derived types 'AlgorithmATransmit' and 'AlgorithmAReceive' i.e. slight variations within the same algorithm depending on direction).

I would also like to have a cleaner separation between the algorithm logic and the serialzed data.

I would be happy to hear your opinions on this. Thanks !

War es hilfreich?

Lösung

The Strategy pattern to me is nothing more than just using object composition to allow a bunch of different strategies can be used in a class AND interchanged in run-time. In your case, you CAN use the Strategy pattern, if you want the Antenna class to change its behavior (the algorithm) in run-time, based on the input values. If this is the case, in the Antenna class, you have an instance variable pointing to a AlgorithmInterface, which is derived by 4 classes: AlgoATransmit, AlgoBTransmit, AlgoAReceive, and AlgoBReceive. Each of these 4 classes would define the real algorithms. Then, you need a client class that checks input value types, and set the Antenna to use the appropriate algorithm.

While I don't see how Command Pattern can be applied, your problem might be also be a good case for the Template Method pattern and you can use it in complement with the Strategy. What you can do is to have an abstract class, let's call it AbstractAlgorithm, which has a "template method" that define the common flow of the algorithms by calling separate functions. These functions will be overriden in the subclasses, e.g. AlgorithmA, AlgorithmB.

The direction of Antenna can be solved by using "hooks" inside the template method. Hooks are basically functions that are optional to override in subclasses.

Here is a simple sample code. Antenna makes use of Object Composition and Strategy, has a variable pointing to the abstract algorithm, which is derived by 2 algorithms. This way, the outline of the algorithms can be specified in one place, and each concrete step is defined in the subclasses. Hope it helps and I hope I understood your problem right.

class Antenna {
    private AbstractAlgorithm algo;
    void SetAlgo(AbstractAlgorithm newAlgo) {
        algo = newAlgo;
    }
}

class AbstractAlgorithm {

    //this is the template method
    void runAlgo() {   
          step1();        //step1 and step2 are two common steps for both algorithms
          step2();
          if (isMatrixValue())
             step3();            //a hook, only AlgoB will override it.
          if (isTransmitting())
             step4();            //a hook, use for transmit
          else if (isReceiving())
             step5();            //a hook, use for receive

    }

    abstract void step1();
    abstract void step2();
    boolean isMatrixValue() {
         return false;         //default value, to not run step3
    }

}

class AlgorithmA {

    void step1() {
         //some implementation
    }
    void step2() {
         //some implementation
    }

    //use the default false value for isMatrixValue(), not to run step3


}


class AlgorithmB {

    void step1() {
         //some implementation
    }
    void step2() {
         //some implementation
    }
    void step3() {
         //some implementation
    }
    boolean isMatrixValue() {
         return true;         //return true and override step3
    }

}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top