Secure Data Stream System - Decorator Pattern Implementation
This is an implementation of the Decorator design pattern for a secure file-writing module where data must be compressed and encrypted before being saved to disk.
Problem Statement
Building a secure file-writing module where data goes through a processing pipeline before hitting the disk. The order of operations matters — data must be encrypted first, then compressed (or vice versa), and the system must be flexible enough to add or remove processing steps without rewriting core logic.
Key Challenge: The data pipeline requires:
- Encryption: Reverse the string ("SystemDesign" → "ngiseDmetsyS")
- Compression: Add a tag ("ngiseDmetsyS" → "(Compressed) ngiseDmetsyS")
- Steps must be stackable in any order
Class Diagram
+----------------+
| DataSource | <-------------------------+
| (Interface) | |
+----------------+ |
| + writeData() | |
+-------+--------+ |
^ |
| (Implements) |
| | (Wraps / Has-A)
+----------+-----------+ +----------+----------+
| | | |
+-----+----------+ +------+-------------+---+ +----------+----------+
| FileDataSource | | DataSourceDecorator |<>----| wrappee field |
+----------------+ | (Abstract) | +---------------------+
| prints to file | +------------------------+
+----------------+ ^
| (Extends)
|
+--------------+--------------+
| |
+--------+----------+ +--------+-----------+
|EncryptionDecorator| |CompressionDecorator|
+-------------------+ +--------------------+
| + writeData(data) | | + writeData(data) |
| reverse string | | add prefix |
| super.write(..) | | super.write(..) |
+-------------------+ +--------------------+
Implementation
package decorator.secureDataStreamSystem;
public class SecureDataStreamSystem {
// ==========================================
// 1. The Component Interface
// ==========================================
interface DataSource {
void writeData(String data);
}
// ==========================================
// 2. The Concrete Component (The Base)
// ==========================================
static class FileDataSource implements DataSource {
@Override
public void writeData(String data) {
System.out.println("Writing to file: " + data);
}
}
// ==========================================
// 3. The Abstract Decorator
// ==========================================
static abstract class DataSourceDecorator implements DataSource {
protected DataSource wrappee; // The next layer in the chain
public DataSourceDecorator(DataSource wrappee) {
this.wrappee = wrappee;
}
@Override
public void writeData(String data) {
wrappee.writeData(data); // Pass it down
}
}
// ==========================================
// 4. Concrete Decorator (Encryption)
// ==========================================
static class EncryptionDecorator extends DataSourceDecorator {
public EncryptionDecorator(DataSource wrappee) {
super(wrappee);
}
@Override
public void writeData(String data) {
// 1. Intercept and Modify the Data (Reverse it)
String encryptedData = new StringBuilder(data).reverse().toString();
System.out.println("[Encryption] Reversing data...");
// 2. Pass the MODIFIED data down the chain
super.writeData(encryptedData);
}
}
// ==========================================
// 5. Concrete Decorator (Compression)
// ==========================================
static class CompressionDecorator extends DataSourceDecorator {
public CompressionDecorator(DataSource wrappee) {
super(wrappee);
}
@Override
public void writeData(String data) {
// 1. Intercept and Modify the Data (Add prefix)
String compressedData = "(Compressed) " + data;
System.out.println("[Compression] Adding compression tag...");
// 2. Pass the MODIFIED data down the chain
super.writeData(compressedData);
}
}
// ==========================================
// 6. Main Driver
// ==========================================
public static void main(String[] args) {
System.out.println("---- Secure File Write Simulation ----\n");
// We wrap from the inside out: File <- Compression <- Encryption
DataSource secureFile = new EncryptionDecorator(
new CompressionDecorator(
new FileDataSource()
)
);
// The client only needs to pass the plain text.
// The decorators handle the rest!
secureFile.writeData("SystemDesign");
}
}
Key Features
- Decorator Pattern: Dynamically adds processing steps without modifying the base class
- Pipeline Processing: Data flows through a chain of transformations in a defined order
- Order Matters: Wrapping order determines the processing sequence
- Single Responsibility: Each decorator handles exactly one transformation
-
Transparent to Client: Client simply calls
writeData()with plain text - Extensible: New processing steps (e.g., hashing, encoding) can be added without modifying existing code
How It Works
-
Component Interface (DataSource): Defines the common
writeData()contract - Concrete Component (FileDataSource): The base — simply writes data to file
- Abstract Decorator (DataSourceDecorator): Holds a reference to the next layer and delegates calls
- Concrete Decorators: Intercept data, transform it, then pass it down the chain
-
Wrapping Order:
EncryptionDecorator → CompressionDecorator → FileDataSource
Top comments (0)