Alle Komponenten sollten ein gemeinsames Interface implementieren, das einfache Operationen wie send(), receive() etc. bereitstellt. Jeder Decorator sollte nur dort eingreifen, wo er Funktionalität hinzufügen will, und den Rest delegieren.
Ziel:
Ein DataStream-Interface mit verschiedenen Dekoratoren:
BaseStream: schreibt Daten in ein Dummy-RegisterLoggingDecorator: loggt alle gesendeten DatenCRCDecorator: fügt am Ende der Nachricht eine einfache CRC-Prüfsumme hinzu
Alle Klassen implementieren die gleiche Schnittstelle, wodurch sie beliebig kombinierbar bleiben.
#include <iostream>
#include <cstdint>
#include <cstring>
class IDataStream {
public:
virtual void send(const uint8_t* data, size_t len) = 0;
virtual ~IDataStream() = default;
};
// --- Basiskomponente: Simulierte Ausgabe ---
class BaseStream : public IDataStream {
public:
void send(const uint8_t* data, size_t len) override {
std::cout << "[BaseStream] Sending: ";
for (size_t i = 0; i < len; ++i) {
std::cout << std::hex << (int)data[i] << " ";
}
std::cout << std::dec << "\n";
}
};
// --- Decorator-Basis-Klasse ---
class StreamDecorator : public IDataStream {
protected:
IDataStream& wrapped;
public:
StreamDecorator(IDataStream& stream) : wrapped(stream) {}
};
// --- Logging-Dekorator ---
class LoggingDecorator : public StreamDecorator {
public:
LoggingDecorator(IDataStream& stream) : StreamDecorator(stream) {}
void send(const uint8_t* data, size_t len) override {
std::cout << "[LoggingDecorator] Logging " << len << " bytes\n";
wrapped.send(data, len);
}
};
// --- CRC-Dekorator ---
class CRCDecorator : public StreamDecorator {
public:
CRCDecorator(IDataStream& stream) : StreamDecorator(stream) {}
void send(const uint8_t* data, size_t len) override {
uint8_t buffer[256];
if (len + 1 > sizeof(buffer)) return; // Sicherheitscheck
memcpy(buffer, data, len);
buffer[len] = calculateCRC(data, len);
std::cout << "[CRCDecorator] Appending CRC\n";
wrapped.send(buffer, len + 1);
}
private:
uint8_t calculateCRC(const uint8_t* data, size_t len) {
uint8_t crc = 0;
for (size_t i = 0; i < len; ++i) {
crc ^= data[i];
}
return crc;
}
};Verwendung
int main() {
BaseStream base;
LoggingDecorator logger(base);
CRCDecorator crc(logger); // Reihenfolge: CRC außen, Logging innen
uint8_t msg[] = { 0xAA, 0xBB, 0xCC };
crc.send(msg, sizeof(msg));
return 0;
}