fstream als Membervariable
-

also erstmal folgendes bild
http://www.imagenetz.de/f084ff3d0/1388646_10201371494701857_346125121_n.jpg.htmles soll das adapter als design pattern verwendet werden(aus der angabe herausgelesen werden).
nund streitigkeiten gibts unten beim crypto interface. den einer sagt, es soll wie oben gemacht werden und der andere sagt:
read und write werden in der abstrakten klasse implementiert.
in der abstrakten klasse eine protected string membervariable. dieser wird dann von den klassen caesar oder von rsa eben kodiert. wir benutzen es sozusagen als puffer.
nun hier ist das problem allerdings, dass eben rsa z.b für das zeichen h eine 3 oder vierstellige reingeschrieben wird und somit jedesmal mit insert zeichen rumgeschoben werden.nun was ist besser von den beiden "schlechten" lösungswegen? oder gibts was besseres?
mfg
ACnut
-
i brauch hüfe
:p
-
leute wo seid ihr?
-
ACnut schrieb:
leute wo seid ihr?
Ich habe deine Frage zehnmal lesen müssen, um sie zu verstehen. Kein Scherz. Wenn du lesbarer schreibst, bekommst du auch eher Antworten.
oder gibts was besseres?
Das Design gefallt mir schon an der Stelle nicht, wo überhaupt die Cryptoklasse die Daten verwaltet. Dateien lesen und Speichern ist nicht die Aufgabe einer solchen Klasse. Sie arbeitet auf codierten Daten, in egal welcher Form. Man gibt codierte Zeichen hinein und bekomme decodierte Zeichen heraus. Sich um das Besorgen dieser Zeichen zu kümmern ist nicht ihre Aufgabe.
Wenn du unbedingt einen Dateicodierer und Decodierer möchtest, dann lass diesen die Cryptoklasse benutzen. Der Dateicodierer kümmert sich dann um die Dateien. Oder besser gesagt: Um einer Datei. Eine Dateiressource pro Instanz. Wenn du irgendwie mehrere Dateien gleichzeitig in einem Objekt behandeln möchtest, dann schreib noch einen Multidateicodierer, der mehrere Dateicodierer besitzt. Und somit sollten sich alle deine Designfragen eigentlich in Luft auflösen.
-
Also Read ist meist ein Decrypt, Write meist ein Encrypt. Und wenn dann richtig modular. Normalerweise arbeitet (De)crypt mit Streams, also Read/Write werden in einer anderen Klasse realisiert.
-
@ACnut
Vererbung ist die engste Art der Koppelung, und daher wenn möglich zu vermeiden.
Vererbung im Sinn von "Klasse erbt von rein abstrakter Inerface-Klasse und implementiert dieses Interface" ist noch OK.
Vererbung ala "abgeleitete Klasse greift auf protected Member der Basisklasse zu" ist super unübersichtlich und sollte tunlichst vermieden werden.Wobei ich mir nicht so sicher bin ob ihr die Aufgabe überhaupt richtig verstanden habt. Euer Diagramm sieht irgendwie bloss verwirrend aus.
Kannst du mal mit Worten beschreiben was ihr machen sollt? Also was vorgegeben ist, und was euer Programm dann können/tun soll?
-
@SeppJ habs selber dann mein posting gelesen und habs ehrlich gesagt selber nicht verstanden. entschuldigung
ja kann die angabe gerne posten:
Entwerfen Sie aus der nachfolgend gegebenen
Spezifikation ein Klassendiagramm, instanzieren Sie dieses und implementieren Sie die Funktionalität
entsprechend:
Die Firma High Speed Software Engineering soll für die beiden Kunden Epcos und Nortel Networks
ein Verschlüsselungssystem zur Verfügung stellen.
Es werden 2 Verschlüsselungsalgorithmen unterstützt: Caesar und RSA.
Die Algorithmen sollen zur Laufzeit austauschbar sein. Benützen Sie dafür ein entsprechendes Design
Pattern. Da die beiden Kunden unterschiedliche Schnittstellen wünschen, verwenden Sie ein
internes Interface und delegieren Sie die Aufrufe der beiden Interfaces mit Hilfe eines geeigneten
Design Pattern an die interne Schnittstelle.wobei eben die schnittstellen gegeben sind(das heißt die interfaces der beiden klienten und von dem unteren interface/bzw. abstrakte klasse im klassendiagramm
bool ReadFile(std::string const & fileName); bool WriteFile(std::string const & fileName); void Encrypt(); void Decrypt();
-
Bisschen umständliches Interface, aber was will man bei solchen Vorgaben machen?

Wozu braucht es da einen Stream-Member? Die Funktionen ReadFile und WriteFile machen eine Datei auf, lesen/schreiben in/aus einen internen Buffer, fertig. Kein Grund, den Stream selbst zwischendurch aufzubewahren.
-
wir sollen halt üben wie man die design patterns benutzt xD
genau das war auch der grund wieso ich das topic erstellt hab.
wer von uns beiden recht hat:
mit puffer arbeiten (string als membervariable)->braucht bei längeren texten viel speicheroder eben mit einer streammembervariable um einzeln die zeichen zu lesen und direkt wieder zurückzuschreiben->was ich persönlich unschön finde, da es meiner meinung nach aufwändiger ist (hat aber der lehrer selbst empfohlen, die zeichen einzeln zu lesen und wieder zurückzuschreiben. auch hat er das mit dem "zwischenlagern" der stream-variable nicht verneint)
-
Hm.
Ich würde das komplett anders aufziehen, aber OK.
Euer Lehrer/Prof will wohl wirklich ein schlechtes Design haben.Wenn ihr die Signaturen von ReadFile, WriteFile, Encrypt und Decrypt nicht anpassen könnt/dürft, dann bleibt nur mehr eine unsaubere Pfusch-Lösung übrig.
In dem Fall würde ich ganz klar die Variante bevorzugen wo
ReadFileundWriteFilein der Basisklasse implementiert sind, und zum "Datenaustausch" ein protectedstd::string(bzw. besser:std::vector<unsigned char>) verwendet wird.Weil es keinen Sinn macht die Funktionalität von
WriteFilein beiden "Crypto" Klassen zu duplizieren. Und weil durch das gemeinsameWriteFileauch der "Contract" zwischen der Basisklasse und den abgeleiteten Klassen einfacher wird: Die abgeleiteten Klassen müssen nur Encrypt/Decrypt so implementieren, dass die im protected Buffer stehenden Daten ver- bzw. entschlüsselt werden. Und nicht mit irgendwelchen Files rumhantieren. Die ganze IO Geschichte ist dann Sache der gemeinsamen Basisklasse.Eine Pfusch-Lösung bleibt es aber trotzdem.
Die Klassen Caesar und RSA sollten nicht von einer Klasse abgeleitet sein, die gleichzeitig noch IO macht.
Besser wäre es wenn die abstrakte "Crypto" Basisklasse gar keinen IO macht, sondern den Datenpuffer als Parameter an die Decrypt bzw. Encrypt Funktion übergeben bekommt.
Die Klasse "Crypto" wäre dann eine rein abstrakte Basisklasse, die selbst gar keinen Code enthält (und auch keine Datenmember).Dann könnte man eine weitere Klasse machen, die man z.B. "FileCrypto" nennt, die den IO Teil implementiert, und den Ver- bzw. Entschlüsselungs-Teil an die "Crypto" Klasse delegiert.
Diese "FileCrypto" Klasse müsste (bzw. sollte) dabei nichtmal "Crypto" Objekte nichtmal als Member halten, sondern bekommt diese wiederrum als Parameter an die Encrypt/Decrypt Funktion mitgegeben.Also inetwa so:
class Crypto { public: virtual void Encrypt(std::vector<unsigned char>& inout_buffer) = 0; virtual void Decrypt(std::vector<unsigned char>& inout_buffer) = 0; }; class RSA : public Crypto // ... class Caesar : public Crypto // ... class FileCrypto { public: void EncryptFile(std::string const& path, Crypto& codec); void DecryptFile(std::string const& path, Crypto& codec); };Die Adapterklassen enthalten dann jeweils ein FileCrypto Member. Die Crypto-Instanzen können im Prinzip lokal im Encrypt/Decrypt Aufruf der jeweiligen Adapterklasse angelegt werden. Bzw. wenn es verlangt ist auch als Member gehalten werden, z.B. wenn man die u.U. aufwendige Initialisierung des RSA Codecs nicht bei jedem Funktionsaufruf machen möchte.
Bzw. genaugenommen ist die FileCrypto Klasse gar keine Klasse, weil ihre Objekte leer sind. Es handelt sich hier lediglich um zwei freie Funktionen. Also sollte man diese auch nicht als Klasse, sondern eben als freie Funktionen modellieren. Wobei es sein kann dass eurem Lehrer/Prof das zu wenig "objektig" ist.
-
ACnut schrieb:
oder eben mit einer streammembervariable um einzeln die zeichen zu lesen und direkt wieder zurückzuschreiben->was ich persönlich unschön finde, da es meiner meinung nach aufwändiger ist
Naja "aufwendiger" würde ich nicht sagen. Ist es zwar, aber das ist nicht immer das beste Kriterium. Es ist komplizierter, in Sinn von komplizierter zu verstehen. Einfach (zu verstehen) ist gut.
(hat aber der lehrer selbst empfohlen, die zeichen einzeln zu lesen und wieder zurückzuschreiben. auch hat er das mit dem "zwischenlagern" der stream-variable nicht verneint)
Also wie das "einzeln einlesen" sich mit RSA vertragen soll erschliesst sich mir nicht ganz. Sollen die Zeichen alle einzeln mit RSA ver- bzw. entschlüsselt werden? Oder soll ein symmetrischer Stream-Cipher verwendet werden, der nur zum Abspeichern des symmetrischen Schlüssels RSA verwendet?
Ist aber im Prinzip wurst.
Wenn man die Daten "streamen" will, dann muss das Interface von "Crypto" geändert werden. Alles andere wäre blanker Wahnsinn.
-
so hätte ich es eigentlich auch gelöst, aber da es in der zeit unmöglich war noch was zu ändern (die abgabe war heute), haben wir es mit der filestreammembervariablenauslagerungs-Methode (ei neues Wort in der deutschen Sprche xD) gelöst.
hätte die antworten bissl früher gebraucht, aber da ich mich schlecht ausgedrückt hab, war es ausshließlich mein fehler
mfg
ACnut