Dynamic Functionality Extension with Decorator
The Decorator pattern enables you to add new responsibilities to objects dynamically, without modifying their code or relying on deep inheritance hierarchies. This approach is especially useful when you want to extend the behavior of individual objects, rather than all instances of a class. By wrapping an object with one or more decorators, you can compose new functionality at runtime. Unlike subclassing, which can lead to a rigid and complex class structure, Decorator allows you to mix and match features flexibly and transparently.
main.cpp
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768#include <iostream> #include <string> #include <memory> // The base Writer interface class Writer { public: virtual ~Writer() = default; virtual void write(const std::string& data) = 0; }; // Concrete Writer implementation class FileWriter : public Writer { public: void write(const std::string& data) override { std::cout << "[FileWriter] Writing: " << data << std::endl; } }; // Decorator base class class WriterDecorator : public Writer { protected: std::unique_ptr<Writer> wrappee; public: WriterDecorator(std::unique_ptr<Writer> w) : wrappee(std::move(w)) {} }; // Logging Decorator class LoggingWriter : public WriterDecorator { public: LoggingWriter(std::unique_ptr<Writer> w) : WriterDecorator(std::move(w)) {} void write(const std::string& data) override { std::cout << "[LoggingWriter] Logging data: " << data << std::endl; wrappee->write(data); } }; // Encryption Decorator class EncryptingWriter : public WriterDecorator { public: EncryptingWriter(std::unique_ptr<Writer> w) : WriterDecorator(std::move(w)) {} void write(const std::string& data) override { std::string encrypted = encrypt(data); std::cout << "[EncryptingWriter] Encrypting data: " << encrypted << std::endl; wrappee->write(encrypted); } private: std::string encrypt(const std::string& input) { std::string result = input; for (auto& c : result) c += 1; // Simple Caesar cipher: shift chars by 1 return result; } }; int main() { std::unique_ptr<Writer> writer = std::make_unique<FileWriter>(); writer = std::make_unique<LoggingWriter>(std::move(writer)); writer = std::make_unique<EncryptingWriter>(std::move(writer)); writer->write("Hello, Decorator!"); }
The Decorator pattern supports the open/closed principle by allowing you to extend an object's behavior without altering its source code. This makes your system open for extension but closed for modification. You can stack multiple decorators to combine features such as logging, encryption, buffering, or compression in any order, giving you highly flexible and reusable components. This compositional approach also helps avoid the exponential growth of subclasses that would be required to support every possible combination of features through inheritance.
Tak for dine kommentarer!
Spørg AI
Spørg AI
Spørg om hvad som helst eller prøv et af de foreslåede spørgsmål for at starte vores chat
Awesome!
Completion rate improved to 10
Dynamic Functionality Extension with Decorator
Stryg for at vise menuen
The Decorator pattern enables you to add new responsibilities to objects dynamically, without modifying their code or relying on deep inheritance hierarchies. This approach is especially useful when you want to extend the behavior of individual objects, rather than all instances of a class. By wrapping an object with one or more decorators, you can compose new functionality at runtime. Unlike subclassing, which can lead to a rigid and complex class structure, Decorator allows you to mix and match features flexibly and transparently.
main.cpp
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768#include <iostream> #include <string> #include <memory> // The base Writer interface class Writer { public: virtual ~Writer() = default; virtual void write(const std::string& data) = 0; }; // Concrete Writer implementation class FileWriter : public Writer { public: void write(const std::string& data) override { std::cout << "[FileWriter] Writing: " << data << std::endl; } }; // Decorator base class class WriterDecorator : public Writer { protected: std::unique_ptr<Writer> wrappee; public: WriterDecorator(std::unique_ptr<Writer> w) : wrappee(std::move(w)) {} }; // Logging Decorator class LoggingWriter : public WriterDecorator { public: LoggingWriter(std::unique_ptr<Writer> w) : WriterDecorator(std::move(w)) {} void write(const std::string& data) override { std::cout << "[LoggingWriter] Logging data: " << data << std::endl; wrappee->write(data); } }; // Encryption Decorator class EncryptingWriter : public WriterDecorator { public: EncryptingWriter(std::unique_ptr<Writer> w) : WriterDecorator(std::move(w)) {} void write(const std::string& data) override { std::string encrypted = encrypt(data); std::cout << "[EncryptingWriter] Encrypting data: " << encrypted << std::endl; wrappee->write(encrypted); } private: std::string encrypt(const std::string& input) { std::string result = input; for (auto& c : result) c += 1; // Simple Caesar cipher: shift chars by 1 return result; } }; int main() { std::unique_ptr<Writer> writer = std::make_unique<FileWriter>(); writer = std::make_unique<LoggingWriter>(std::move(writer)); writer = std::make_unique<EncryptingWriter>(std::move(writer)); writer->write("Hello, Decorator!"); }
The Decorator pattern supports the open/closed principle by allowing you to extend an object's behavior without altering its source code. This makes your system open for extension but closed for modification. You can stack multiple decorators to combine features such as logging, encryption, buffering, or compression in any order, giving you highly flexible and reusable components. This compositional approach also helps avoid the exponential growth of subclasses that would be required to support every possible combination of features through inheritance.
Tak for dine kommentarer!