Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lære Dynamic Functionality Extension with Decorator | Structural Patterns
Quizzes & Challenges
Quizzes
Challenges
/
C++ Design Patterns

bookDynamic 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

main.cpp

copy
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.

question mark

What is a primary benefit of using the Decorator pattern in C++?

Select the correct answer

Alt var klart?

Hvordan kan vi forbedre det?

Takk for tilbakemeldingene dine!

Seksjon 3. Kapittel 2

Spør AI

expand

Spør AI

ChatGPT

Spør om hva du vil, eller prøv ett av de foreslåtte spørsmålene for å starte chatten vår

Awesome!

Completion rate improved to 10

bookDynamic Functionality Extension with Decorator

Sveip for å vise menyen

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

main.cpp

copy
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.

question mark

What is a primary benefit of using the Decorator pattern in C++?

Select the correct answer

Alt var klart?

Hvordan kan vi forbedre det?

Takk for tilbakemeldingene dine!

Seksjon 3. Kapittel 2
some-alt