Search code examples
c++constructorprivateobserver-patternlookup-tables

Best pattern for Lookup Table with different internal representations? Observer pattern?


I write my own class LookupTable, which gets as an input

  • a map of keypoints and corresponding RGB values

OR

  • 3 channels (Red, Green, Blue) and within each channel there are keypoints for that channel and corresponding values in those keypoints for red, green, and blue.

The LookupTable class can be constructed differently, from different data structures. I keep 3 internal data structures :

1. map<point, pixel>
2. vector<pixel> 
3. struct my{
    map<float, value> red; 
    map<float, value> green;  
    map<float, value> blue; }

LookupTable class can be constructed from 1 or 3 and 2 is always calculated therefore "depends" on them.

Problems:

  1. how do I know from which data structure (1 or 3) should I calculate 2 ?
  2. if first 1 is filled in, then 3 filled in, how to keep track of what is going on in my class? Observer pattern seems an overkill...
  3. straightforward solution - use several booleans -- is not good, it is difficult to maintain and add new data representations in the future, even I understand this.
  4. Ideally,

construct(map<point, pixel>) OR

construct(struct my)

needs to execute only once, and the other times it is called - just return the value

(Those methods are instead of constructors, which are private)


Solution

  • You should only have one way to do things in your implementation. There is no need to store different structures to achieve the same goal. Just present two facades to the user via your public API.

    Assuming pixel looks something like (pseudo code warning):

    class pixel{
      float red, green, blue;
      pixel(float, float, float);
      float getRed();
      ...
    }
    

    Then your LookupTable (terrible name by the way... ColourPanel or something like that would be more descriptive):

    class LookupTable{
      std::map<point, pixel> pointColours;
      void colourThePoint(point, pixel);
      void colourThePoint(point, float, float, float);
      // the pixel returned gives them "getRed" "getGreen" etc... 
      // So Don't Repeat Yourself (DRY) by replicating that functionality here.
      pixel getThePointColout(point); 
      void applyManipulation(std::function<void(pixel)> manip) {
        std::for_each( pointColours.begin(), pointColours.end(), manip );
      }
      ...
     }
    

    BASED ON YOUR COMMENTS I have added a way to apply a manipulation function to the elements. That manipulation function can look something like this:

    void colourMePurple( pixel& original ){
       pixel.increaseBlue(32).increaseRed(32).decreaseGreen(32);
    }
    

    And would be used like this:

    LookupTable myColours;
    ...
    myColours.applyManipulation(colourMePurple);