You are on the right track with the [decorator][1] pattern you suggested. You also want an [adapter][2] to help you unite the public API.
###You should be looking for something like this:
*This is not a concrete language. It is a generic approach, the **any** keyword is there to represent it may be of any type, in a language like C# you can replace it with templates (**<T>**).*
interface Compression
{
Compress(data : any) : any;
}
interface Encryption
{
Encrypt(data : any) : any;
}
interface DataProcessing
{
Process(data : any) : any;
}
class CompressionDecorator : DataProcessing
{
private compression : Compression;
Process(data : any) : any
{
return this.compression.Compress(data);
}
}
class EncryptionDecorator : DataProcessing
{
private encryption : Encryption;
Process(data : any) : any
{
return this.encryption.Encrypt(data);
}
}
class CompressionEncryptionDecorator : DataProcessing
{
private compression : Compression;
private encryption : Encryption;
Process(data : any) : any
{
return this.encryption.Encrypt(
this.compression.Compress(data)
);
}
}
Your business logic becomes as simple as:
class DataService
{
private dataProcessing : DataProcessing;
public DataService(dataProcessing : DataProcessing)
{
this.dataProcessing = dataProcessing;
}
public TheProcess(data) : any
{
return this.dataProcessing.Process(data);
}
}
This way you successfuly move all the `if`s from the business layer to where they really belong, Factories. That is also where the `DataService` class will be constructed along with its dependencies.
[1]: https://en.wikipedia.org/wiki/Decorator_pattern
[2]: https://en.wikipedia.org/wiki/Adapter_pattern