Designproblem: Unsichere Kollaboration



  • zuerst mal die Situation: Objekt A will das frisch erzeugte Objekt B mit einer Reihe von Einträgen füttern, die aus einer Datei eingelesen werden. Die Anzahl ist von vornherein bekannt, was eine Implementation in Form eines Vektors nahelegt.

    Man stelle sich nun folgende Kollaboration vor:

    1: A führt aus B.setNumItems(n);
    2: n-mal A führt aus B.addItem(Item soundso); // dabei führt B auch eine Verarbeitung der einzelnen Items durch

    (Die Trennung in A und B gibt es, damit B nicht vom Dateiformat abhängig ist.)
    Nun ist das schön und gut, aber leider etwas wackelig. addItem darf nur aufgerufen werden, wenn vorher die Anzahl der Items festgelegt wurde (könnte man zur Not im Konstruktor von B erzwingen) und bisher noch nicht alle Items eingefügt wurde. Weiterhin ist B nach der Aktion nur gültig, wenn alle Items übertragen wurden. Man könnte das alles durch Nutzung einer dynamischen Datenstruktur innerhalb von B lösen, aber das ist unnötig ineffizient.

    Das erste was mir eingefallen ist, wäre, dass B sich die einzelnen Items von A selbst abholt. Aber dadurch entsteht eine zusätzliche Abhängigkeit B -> A.

    Eine andere Möglichkeit wäre, dass A einen Vektor an B übergibt. Das erzeugt aber ebenfalls eine Abhängigkeit von der Implementation von A, wenn es nicht unnötig ineffizient sein soll.

    Gibt es eine schöne Lösung, die keine unnötigen zusätzlichen Abhängigkeiten einführt und eine sichere Kollaboration erzwingt?

    Ich denk wahrscheinlich wieder viel zu kompliziert ...



  • Ich weiss nicht genau, ob ich dein Problem verstehe, aber ich hab mal einen Lösungsansatz

    template<class T> class B
    {
      //...
    public:
      B(const T*array,size_t pos);
    };
    
    template<class T> class filler
    {
      size_t fill;
      size_t pos;
      T *array;
    public:
      filler() : fill(0),pos(0),array(NULL) { }
      filler(size_t n) : fill(n),pos(0),array(new T[n]) { }
      ~filler() { delete[]array; }
      void setNumItem(size_t n) 
      { 
        fill=n; 
        delete[]array;
        array=new T[n];
      }
      void addItem(const T& obj)
      {
        array[pos++]=obj;
      }
      B<T> getB(void)
      {
        if(fill==pos)
          return B<T>(array,fill);
      }
    };
    
    template<class T> class A
    {
      B<T> b;
      //...
      void foo(void)
      {
         //einlesen
         filler<T> f(n);
         for(size_t i=0;i<n;++i)
           f.addItem(item);
         b=f.getB();
      }
    };
    

    (vorhin hatte ich noch eine bessere Idee, die hab ich aber vergessen 😞 )



  • Hallo,
    also ganz intuitiv würde ich sagen, dass diese fütter-Methode nach B gehört. B sich also selbst füttern sollte. Die Abhängigkeit zwischen A und B könntest du dann so umbiegen, dass beide von einer abstrakte Klassen (oder auch einer Schnittstelle) abhängig sind.



  • Danke.

    Ich hab irgendwie immer Hemmungen, abstrakte Klassen nebst virtuellen Funktionen zu verwenden; wieso eigentlich ... 😕


Anmelden zum Antworten