Breaking SOLID Principles in multiple implementation of an Interface - c#

I am facing a problem with dependency inversion in a factory method and it is also breaking Open Closed principle. My code looks like below codes
public interface IWriter
{
void WriteToStorage(string data);
}
public class FileWriter : IWriter
{
public void WriteToStorage(string data)
{
//write to file
}
}
public class DBWriter : IWriter
{
public void WriteToStorage(string data)
{
//write to DB
}
}
Now I an using a factory class to solve the object creation. It look like below code
public interface IFactory
{
IWriter GetType(string outputType);
}
public class Factory : IFactory
{
public IWriter GetType(string outputType)
{
IWriter writer = null;
if (outputType.Equels("db"))
{
writer = new FileWriter();
}
else if (outputType.Equels("db"))
{
writer = new DBWriter();
}
}
}
Now the problem is the Factory class is breaking Open closed principle so it also breakes Dependency Inversion Principle
And then
public interface ISaveDataFlow
{
void SaveData(string data, string outputType);
}
public class SaveDataFlow : ISaveDataFlow
{
private IFactory _writerFactory = null;
public SaveDataFlow(IFactory writerFactory)
{
_writerFactory = writerFactory;
}
public void SaveData(string data, string outputType)
{
IWriter writer = _writerFactory.GetType(outputType);
writer.WriteToStorage(data);
}
}
As the above factory class is breaking the dependency inversion I remove the Factory class and change the SaveDataFlow class like below
public class SaveDataFlow : ISaveDataFlow
{
private IWriter _dbWriter = null;
private IWriter _fileWriter = null;
public SaveDataFlow([Dependency("DB")]IWriter dbWriter,
[Dependency("FILE")]IWriter fileWriter)
{
_dbWriter = dbWriter;
_fileWriter = fileWriter;
}
public void SaveData(string data, string outputType)
{
if (outputType.Equals("DB"))
{
_dbWriter.WriteToStorage(data);
}
else if (outputType.Equals("FILE"))
{
_fileWriter.WriteToStorage(data);
}
}
}
And resolved those dependencies using Unity Framework
container.RegisterType<IWriter, DBWriter>("DB");
container.RegisterType<IWriter, FileWriter>("FILE");
Yet eventually I am ending up breaking Open Closed Principle.
I need a better design/solution to solve such a problem yet I must follow SOLID Principles.

I would simply turn it into a strategy pattern:
namespace UnityMutliTest
{
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.Unity;
class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IWriter, FileWriter>("file");
container.RegisterType<IWriter, DbWriter>("db");
container.RegisterType<IWriterSelector, WriterSelector>();
var writerSelector = container.Resolve<IWriterSelector>();
var writer = writerSelector.SelectWriter("FILE");
writer.Write("Write me data");
Console.WriteLine("Success");
Console.ReadKey();
}
}
interface IWriterSelector
{
IWriter SelectWriter(string output);
}
class WriterSelector : IWriterSelector
{
private readonly IEnumerable<IWriter> writers;
public WriterSelector(IWriter[] writers)
{
this.writers = writers;
}
public IWriter SelectWriter(string output)
{
var writer = this.writers.FirstOrDefault(x => x.CanWrite(output));
if (writer == null)
{
throw new NotImplementedException($"Couldn't find a writer for {output}");
}
return writer;
}
}
interface IWriter
{
bool CanWrite(string output);
void Write(string data);
}
class FileWriter : IWriter
{
public bool CanWrite(string output)
{
return output == "FILE";
}
public void Write(string data)
{
}
}
class DbWriter : IWriter
{
public bool CanWrite(string output)
{
return output == "DB";
}
public void Write(string data)
{
}
}
}
You can have as many IWriters as you want, just register them:
container.RegisterType<IWriter, LogWriter>("log");
You can even implement decorators over the writers if you want as well.
You use the (badly named) IWriterSelector as the implementation on how to select your writer, this should be concerned with only getting a writer! The throw exception here is really useful, it will fail fast if there is no implementation that suits your needs!!
If you ever have Open Closed problems, either use Strategy or Template patterns to overcome.
I use this pattern all the time, to great effect.
I've created a little extension method to prevent you having to name your instances:
static class UnityExtensions
{
public static void RegisterMultipleType<TInterface, TConcrete>(this IUnityContainer container)
{
var typeToBind = typeof(TConcrete);
container.RegisterType(typeof(TInterface), typeToBind, typeToBind.Name);
}
}
container.RegisterMultipleType<IWriter, FileWriter>();

Solution 1
Choose before instantiation and use scopes
using(var scope = new Scope(unity))
{
scope.register<IWriter, ConcreteWriter>();
var flow = scope.Resolve<ISaveDataFlow>();
}
Solution 2
Inject your strategy at runtime.
ISaveDataFlow flow = ....
IWriter writer = GetWriterBasedOnSomeCondition();
flow.SaveData(data, writer);
I suspect that solution 2 is closer to what you are trying to achieve. Remember, you don't need to pass around a string to describe the strategy you want to use.
You can instead pass around the actual strategy you want to use, in this case, the actual IWriter, you want to use.
Then what you can do instead is have metadata on each IWriter to help the user choose which IWriter to use.
For example
public interface IWriter
{
void WriteData(data);
string Name {get;}
}
void GetWriterBasedOnSomeCondition()
{
Dictionary<string, IWriter> writers = ...ToDictionary(x => x.Name);
var choice = Console.ReadLine();
return writers[choice];
}

I tend to use one of these approaches.
1. Break into different interfaces
public interface IWriter
{
void WriteToStorage(string data);
}
public interface IFileWriter : IWriter
{
}
public interface IDBWriter: IWriter
{
}
public class FileWriter : IFileWriter
{
public void WriteToStorage(string data)
{
//write to file
}
}
public class DBWriter : IDBWriter
{
public void WriteToStorage(string data)
{
//write to DB
}
}
Pros: You can inject the correct implementation based on the interface, which doesn't break the OCP.
Cons: You have empty interfaces.
2. Use an enum to separate them (strategy pattern)
public interface IWriter
{
void WriteToStorage(string data);
StorageType WritesTo { get; }
}
public enum StorageType
{
Db = 1,
File = 2
}
public class Factory : IFactory
{
public IEnumerable<IWriter> _writers;
public Factory(IWriter[] writers)
{
_writers = writers;
}
public IWriter GetType(StorageType outputType)
{
IWriter writer = _writers.FirstOrDefault(x => x.WritesTo == outputType);
return writer;
}
}
Pros: You can inject them both and then use the one you want by using the enum.
Cons: I guess it kinda breaks the OCP-principle the same way as in your first example.
More about the strategy pattern in this excellent answer from Mark Seemann.
3. Build a factory that creates items based on a func.
In your registration:
container.RegisterType<IWriter, DBWriter>("DB");
container.RegisterType<IWriter, FileWriter>("FILE");
container.RegisterType<IFactory, Factory>(
new ContainerControlledLifetimeManager(),
new InjectionConstructor(
new Func<string, IWriter>(
writesTo => container.Resolve<IWriter>(writesTo));
And your factory
public class Factory : IFactory
{
private readonly Func<string, IWriter> _createFunc;
public Factory(Func<string, IWriter> createFunc)
{
_createFunc = createFunc;
}
public IWriter CreateScope(string writesTo)
{
return _createFunc(writesTo);
}
}
Pros: Moves the entire dependency to the registration.
Cons: A wrapper for a service-locator pattern. Can be a bit hard to read.
None of the examples above is perfect, as each of them has their pros and cons.
Similiar question here:
Inject require object depends on condition in constructor injection

In .NET Core (it's not clear from the question what framework is being used), you can use the built-in DI to achieve the strategy pattern quite easily with very little code.
In Startup.ConfigureServices:
services
.AddScoped<IWriter, FileWriter>()
.AddScoped<IWriter, DBWriter>()
.AddScoped<ISaveDataFlow, SaveDataFlow>();
Add an method to IWriter for the strategy algorithm:
public interface IWriter
{
bool CanWrite(string outputType);
void WriteToStorage(string data);
}
public class FileWriter : IWriter
{
bool CanWrite(string outputType) => outputType == "FILE";
public void WriteToStorage(string data) {}
}
public class DBWriter : IWriter
{
bool CanWrite(string outputType) => outputType == "DB";
public void WriteToStorage(string data) {}
}
Then change the constructor of SaveDataFlow to use a collection type, and change SaveData to call the algorithm method of all resolved IWriter types.
public class SaveDataFlow : ISaveDataFlow
{
private readonly IWriter _writers;
public SaveDataFlow(IEnumerable<IWriter> writers)
{
_writers= writers;
}
public void SaveData(string data, string outputType)
{
_writers.Single(w => w.CanWrite(outputType)).WriteToStorage(data);
}
}
This now complies with the Open/Closed Principle as the concrete selection is only within the concrete classes themselves.

Related

Is BaseClass is allowed in strategy pattern

I have created a solution to read/process various kinds of files, e.g. XML, JSON, txt.
public interface IFileProcessor
{
TOutput Process<TInput, TOutput>(TInput input);
}
public abstract class FileProcessorBase
{
protected readonly FileInfo fileInfo;
protected FileProcessorBase(FileInfo fileInfo)
{
this.fileInfo = fileInfo;
}
protected abstract TOutput Load<TOutput>();
}
And the concrete class as follows.
public class JsonFileProcessor : FileProcessorBase, IFileProcessor
{
public JsonFileProcessor(FileInfo fileInfo) : base(fileInfo)
{
}
public TOutput Process<TInput, TOutput>(TInput from)
{
//Call Load Method
string res = Load<string>();
return (TOutput)Convert.ChangeType(res, typeof(TOutput), CultureInfo.InvariantCulture);
}
protected override TOutput Load<TOutput>()
{
string res = "JSON Load method";
return (TOutput)Convert.ChangeType(res, typeof(TOutput), CultureInfo.InvariantCulture);
}
}
Concrete class for XML
public class XMLFileProcessor : FileProcessorBase, IFileProcessor
{
public XMLFileProcessor(FileInfo fileInfo) : base(fileInfo)
{
}
public TOutput Process<TInput, TOutput>(TInput from)
{
string res = Load<string>();
return (TOutput)Convert.ChangeType(res, typeof(TOutput));
}
protected override TOutput Load<TOutput>()
{
string xml = "XML";
return (TOutput)Convert.ChangeType(xml, typeof(TOutput));
}
}
and now this is factory class
public class FileProcessorFactory
{
static readonly Dictionary<string, IFileProcessor> fileProcessor;
static FileProcessorFactory()
{
fileProcessor = new Dictionary<string, IFileProcessor>();
fileProcessor.Add("XML", new XMLFileProcessor(new FileInfo(""));
fileProcessor.Add("JSON", new JsonFileProcessor(new FileInfo(""));
}
public static IFileProcessor GetFileProcessor(string key)
{
return fileProcessor[key];
}
}
Below is FileProcessorService class
public class FileProcessorService
{
IFileProcessor fileProcessor;
public FileProcessorService(IFileProcessor fileProcessor)
{
this.fileProcessor = fileProcessor;
}
public TOutput Process<TInput, TOutput>(TInput from)
{
return fileProcessor.Process<TInput, TOutput>(from);
}
}
Now Finally, I'm calling through this way.
IFileProcessor fileProcessor = FileProcessorFactory.GetFileProcessor("XML");
FileProcessorService fileProcessorService = new FileProcessorService(fileProcessor);
var XMLResult = fileProcessorService.Process<string, string>("");
Can I use base class in strategy pattern, If not what would be proposed solution.
This may help answer your specific question with regards whether their are any hard rules to say that the strategy pattern should not inherit any base implementation.
Can i use inheritance instead of implement an interface in strategy pattern?
In terms of your code have you considered passing an interface that has a method to return the stream of data, as opposed to using concrete FileInfo - as you could then remove base class entirely.

Using the Decorator Pattern to Conditionally Replace Behaviour Instead of Extending

Initially I had this structure:
interface IFileBackup
{
void Backup();
}
class BackUpMechanism1 : IFileBackup
{
void Backup()
{
//Back it up
}
}
class BackUpMechanism2 : IFileBackup
{
void Backup()
{
//Back it up in another way
}
}
class Client
{
//Instantiation of both mechanisms
//
try
{
backUpMechanism1.Backup();
}
catch(Exception ex)
{
backupMechanism2.Backup();
}
}
I was told that this was not a very clean design and to redesign it using the decorator pattern. The client should not know about the two back up mechanisms but just call backup and then the first mechanism should try to back up the file and if that fails then use mechanism 2. However I don't understand how to use the decorator pattern because from my understanding it extends functionality but doesn't replace functionality - which is what I want... How do I archive that? I have tried the following:
interface IFileBackup
{
void Backup();
}
class BackupMechanism1 : IFileBackup
{
public void Backup()
{
try
{
Console.WriteLine("Trying to back up to the cloud...");
throw new Exception();
}
catch(Exception ex)
{
Console.WriteLine("Oops that failed. We need to back up locally instead...");
}
}
}
class BackupMechanism2 : IFileBackup
{
IFileBackup _fileBackup;
public BackupMechanism2(IFileBackup fileBackup)
{
_filebackup = fileBackup;
}
public void Backup()
{
//All examples I have seen does this. But doesn't make sense in my case?
_fileBackup.Backup();
Console.WriteLine("Backing up locally");
}
}
//The client does not care about how the backup is done
class Client
{
static void Main()
{
//This is not right, but not sure what I should do in the client.
BackupMechanism2 localBackup = new BackupMechanism2(new BackupMechanism1());
localBackup.Backup();
Console.Read();
}
}
So essentially what I want to achieve is to have two backup mechanisms. Have the client just say backup I don't care how. Let the first mechanism try it's backup method if that fails then try the second method. I'm trying to use the decorator pattern to extend(replace) the backup behaviour of the first mechanism if it fails. I'm struggling to come up with a design that makes sense.
A very clean approach of implementing this would be adding a composite IFileBackup taking an array of IFileBackup objects, and trying them one by one until a working solution is found:
class CompositeBackup {
private readonly IFileBackup[] chain;
public CompositeBackup(params IFileBackup[] chain) {
this.chain = chain.ToArray();
}
public void Backup() {
foreach (var backup in chain) {
try {
backup.Backup();
return;
} catch {
continue;
}
}
throw new InvalidOperationException();
}
}
Now the client simply does this:
IFileBackup backup = new CompositeBackup(
new BackupMechanism1()
, new BackupMechanism2()
);
backup.Backup();
If you later decide to add BackupMechanism3 and BackupMechanism4, the user would need to add another object to the chain of backups. The rest of the code would remain unchanged. In addition, backup mechanisms themselves would remain unaware of other mechanisms' existence, which also simplifies the code.
The decorator pattern, in this case, can be used to provide fallback implementations. You can find plenty of obvious examples in the .Net streams implementation.
So with that in mind, your code should look something like this:
class abstract BaseFileBackup
{
internal BaseFileBackup Fallback;
internal BaseFileBackup(BaseFileBackup fallback) { Fallback = fallback; }
internal BaseFileBackup() { }
internal abstract void DoBackupWork();
internal void Backup()
{
try { DoBackupWork(); }
catch { if(Fallback != null) Fallback.Backup(); else throw; }
}
}
class BackUpMechanism1 : BaseFileBackup
{
internal BackUpMechanism1 (BaseFileBackup fallback): base(fallback) {}
internal BackUpMechanism1 (): base() {}
internal void DoBackupWork()
{
//Back it up
}
}
class BackUpMechanism2 : BaseFileBackup
{
internal BackUpMechanism2 (BaseFileBackup fallback): base(fallback) {}
internal BackUpMechanism2 (): base() {}
internal void DoBackupWork()
{
//Back it up in another way
}
}
// and to call it
class Client
{
static void Main()=>
new BackupMechanism2(new BackupMechanism1()).Backup();
}
Decorator Pattern is the WRONG choice in this scenario.
The problem that you are dealing with here is
under condition x call one method
under condition y call a different method
...
This is the precondition for the Strategy Pattern, and your initial solution was quite close to that. The problem in my mind is that you are using an Exception to determine the program flow, which is a BAD thing to do: exceptions cost stack space, and they should only be thrown under EXCEPTIONAL circumstances. Whereas in your case, it is expected that a given strategy will not work
IFileBackupStrategy
{
bool Backup(File fileToBackup);
}
IFileBackupContext
{
File ForBackup { set; }
bool Backup();
}
class CloudBackUp : IFileBackupStrategy
{
private bool _success;
public bool Backup(File fileToBackup)
{
// code to do backup omitted
// it will set the value of _success to false if it was unsuccessful
return _success;
}
}
class LocalBackUp : IFileBackupStrategy
{
private bool _success;
public bool Backup(File fileToBackup)
{
// code to do backup omitted
// it will set the value of _success to false if it was unsuccessful
return _success;
}
}
public class FileBackupContext : IFileBackupContext
{
private IEnumerable<IFileBackupStrategy> _backupStrategies
public Context(IEnumerable<IFileBackupStrategy> backupStrategies)
=> _backupStrategies = backupStrategies;
public File ForBackup { set; private get; }
public bool Backup()
{
bool successFlag;
foreach(var strategy in _backupStrategies)
{
successFlag = strategy.Backup(ForBackup);
if(successFlag) break;
}
return successFlag;
}
}
In this case, all that the client needs to be aware of is the IFileBackupContext, and not the strategy employed to do the saving.
public class MyBackupClient
{
private IFileBackupContext _context;
public MyBackupClient(IFileBackupContext context) => _context = context;
void SomeMethodThatInvokesBackingUp()
{
_context.ForBackup = new File(/* */);
if(!_context.Backup())
{
Console.WriteLine("Failed to backup the file");
}
}
}
The beauty of this design is that you can add more IFileBackupStrategy implementations, register them with your DI Container and voila they are instantly available to the client without a single code change or the need for re-compilation (though that will ultimately depend upon how you are populating your DI Container)
The decorator pattern is a method of adhering to the O principle in SOLID: which is
Open for extension and closed for modification
This means that you would use the decorator pattern to decorate an existing class, one that should not be changed and yet does not exhibit the behaviour required. The clue is in the name of the pattern: Decorator adds something, it does not change anything.
The Decorator Pattern is a Structural Pattern, whereas the Strategy Pattern, and what you are looking for, is a Behavioural Pattern
This example can be extended of course to report back the strategy which was ultimately employed, and also (if required) any reasoning for why alternate strategies were not.
Edited: in response to Blindy's comment below. Here is the paradigm for the decorator pattern, which should demonstrate how it is not the correct pattern for this problem:
class Image
{
void Render() { /* */ }
}
class FramedImage : Image
{
private Image _originalImage;
public FramedImage(Image original) => _originalImage = original;
new public void Render()
{
/* code to render a frame */
_originalImage.Render();
}
}
Image originalImage = new Image();
Image framedImage = new FramedImage(originalImage);
Image toRender = originalImage;
toRender.Render() // Renders the original image
toRender = framedImage;
toRender.Render(); // Renders the original image in a frame
It should be observed that there is no need to assign each Image to the toRender variable, that is done solely to demonstrate that a decorator is a decorated.
As you can see from this example, the decorator pattern adds behaviour, and it also invokes the decorated item's behaviour.
Edited: Further to the question posed by DSF below. Here is the full listing for a console app demonstrating how to achieve this using Unity 5.8.6
The code takes advantage of the new Tuple from C# 7.0.
I've just used some random number generation to determine whether or not each strategy implementation succeeds in performing its task.
using System;
using System.Collections.Generic;
using System.IO;
using Unity;
using Unity.Injection;
namespace StrategyPattern
{
public interface IFileBackupContext
{
FileStream ForBackup { set; }
(bool success, string strategy) Backup();
}
public interface IFileBackupStrategy
{
(bool success, string name) Backup(FileStream fileToBackup);
}
internal class LocalBackUp : IFileBackupStrategy
{
private bool _success = false;
public (bool success, string name) Backup(FileStream fileToBackup)
{
// code to do backup omitted
var random = new Random(DateTime.Now.Millisecond);
_success = (random.Next() % 3) == 0;
if(_success) fileToBackup.Close();
// it will set the value of _success to false if it was unsuccessful
return (_success, "LocalBackUp");
}
}
internal class CloudBackUp : IFileBackupStrategy
{
private bool _success = false;
public (bool success, string name) Backup(FileStream fileToBackup)
{
// code to do backup omitted
var random = new Random(DateTime.Now.Millisecond);
_success = (random.Next() % 3) == 0;
if (_success) fileToBackup.Close();
// it will set the value of _success to false if it was unsuccessful
fileToBackup.Close();
return (_success, "CloudBackUp");
}
}
public class FileBackupContext : IFileBackupContext
{
private readonly IEnumerable<IFileBackupStrategy> _backupStrategies;
public FileBackupContext(IEnumerable<IFileBackupStrategy> backupStrategies)
=> _backupStrategies = backupStrategies;
public FileStream ForBackup { set; private get; }
public (bool success, string strategy) Backup()
{
foreach (var strategy in _backupStrategies)
{
var (success, name) = strategy.Backup(ForBackup);
if (success) return (true, name);
}
return (false, "");
}
}
public class MyBackupClient
{
private IFileBackupContext _context;
public MyBackupClient(IFileBackupContext context) => _context = context;
public void BackgUpMyFile()
{
_context.ForBackup = new FileStream("d:\\myfile", FileMode.OpenOrCreate);
(bool success, string strategy) = _context.Backup();
if (!success)
{
Console.WriteLine("Failed to backup the file");
return;
}
Console.WriteLine($"File backed up using [{strategy}] strategy");
}
}
public class Bootstrap
{
private readonly IUnityContainer _container;
public Bootstrap()
{
_container = new UnityContainer();
_container.RegisterType<IFileBackupContext, FileBackupContext>();
_container.RegisterType<IFileBackupStrategy, LocalBackUp>("local");
_container.RegisterType<IFileBackupStrategy, CloudBackUp>("cloud");
_container.RegisterType<MyBackupClient>();
_container.RegisterType<Func<IEnumerable<IFileBackupStrategy>>>(new InjectionFactory(c =>
new Func<IEnumerable<IFileBackupStrategy>>(() =>
new[]
{
c.Resolve<IFileBackupStrategy>("local"),
c.Resolve<IFileBackupStrategy>("cloud")
}
)));
}
public MyBackupClient GetClient() => _container.Resolve<MyBackupClient>();
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press ESC to quit ...");
Console.WriteLine("Press any other key to try again.");
Console.WriteLine();
var client = new Bootstrap().GetClient();
do
{
client.BackgUpMyFile();
} while (Console.ReadKey().Key != ConsoleKey.Escape);
}
}
}

Appropriate design pattern for the payment modules c#

As i am learning through design pattern concept and also wanted to implement the payment modules in my project using the proper design pattern. So for that I have created some sample code.
Currently I have two concrete implementation for the payment PayPal and Credit Card. But the concrete implementation will be added further on the project.
Payment Service
public interface IPaymentService
{
void MakePayment<T>(T type) where T : class;
}
Credit Card and Pay Pal Service
public class CreditCardPayment : IPaymentService
{
public void MakePayment<T>(T type) where T : class
{
var creditCardModel = (CreditCardModel)(object)type;
//Implementation CreditCardPayment
}
}
class PayPalPayment : IPaymentService
{
public void MakePayment<T>(T type) where T : class
{
var payPalModel = (PayPalModel)(object)type;
//Further Implementation will goes here
}
}
Client Code Implementation
var obj = GetPaymentOption(payType);
obj.MakePayment<PayPalModel>(payPalModel);
Get Payment Option
private static IPaymentService GetPaymentOption(PaymentType paymentType)
{
IPaymentService paymentService = null;
switch (paymentType)
{
case PaymentType.PayPalPayment:
paymentService = new PayPalPayment();
break;
case PaymentType.CreditCardPayment:
paymentService = new CreditCardPayment();
break;
default:
break;
}
return paymentService;
}
I thought of implementing this modules using strategy design pattern, and I got deviated from Strategy and ended up doing this way.
Is this a proper way for creating the payment modules. Is there a more better approach of solving this scenario. Is this a design pattern?
Edited:
Client Code:
static void Main(string[] args)
{
PaymentStrategy paymentStrategy = null;
paymentStrategy = new PaymentStrategy(GetPaymentOption((PaymentType)1));
paymentStrategy.Pay<PayPalModel>(new PayPalModel() { UserName = "", Password = "" });
paymentStrategy = new PaymentStrategy(GetPaymentOption((PaymentType)2));
paymentStrategy.Pay<CreditCardModel>(
new CreditCardModel()
{
CardHolderName = "Aakash"
});
Console.ReadLine();
}
Strategy:
public class PaymentStrategy
{
private readonly IPaymentService paymentService;
public PaymentStrategy(IPaymentService paymentService)
{
this.paymentService = paymentService;
}
public void Pay<T>(T type) where T : class
{
paymentService.MakePayment(type);
}
}
Does this update inlines with the Strategy Pattern?
One major drawback of using an abstract factory for this is the fact that it contains a switch case statement. That inherently means if you want to add a payment service, you have to update the code in the factory class. This is a violation of the Open-Closed Principal which states that entities should be open for extension but closed for modification.
Note that using an Enum to switch between payment providers is also problematic for the same reason. This means that the list of services would have to change every time a payment service is added or removed. Even worse, a payment service can be removed from the strategy, but still be an Enum symbol for it even though it isn't valid.
On the other hand, using a strategy pattern doesn't require a switch case statement. As a result, there are no changes to existing classes when you add or remove a payment service. This, and the fact that the number of payment options will likely be capped at a small double-digit number makes the strategy pattern a better fit for this scenario.
Interfaces
// Empty interface just to ensure that we get a compile
// error if we pass a model that does not belong to our
// payment system.
public interface IPaymentModel { }
public interface IPaymentService
{
void MakePayment<T>(T model) where T : IPaymentModel;
bool AppliesTo(Type provider);
}
public interface IPaymentStrategy
{
void MakePayment<T>(T model) where T : IPaymentModel;
}
Models
public class CreditCardModel : IPaymentModel
{
public string CardHolderName { get; set; }
public string CardNumber { get; set; }
public int ExpirtationMonth { get; set; }
public int ExpirationYear { get; set; }
}
public class PayPalModel : IPaymentModel
{
public string UserName { get; set; }
public string Password { get; set; }
}
Payment Service Abstraction
Here is an abstract class that is used to hide the ugly details of casting to the concrete model type from the IPaymentService implementations.
public abstract class PaymentService<TModel> : IPaymentService
where TModel : IPaymentModel
{
public virtual bool AppliesTo(Type provider)
{
return typeof(TModel).Equals(provider);
}
public void MakePayment<T>(T model) where T : IPaymentModel
{
MakePayment((TModel)(object)model);
}
protected abstract void MakePayment(TModel model);
}
Payment Service Implementations
public class CreditCardPayment : PaymentService<CreditCardModel>
{
protected override void MakePayment(CreditCardModel model)
{
//Implementation CreditCardPayment
}
}
public class PayPalPayment : PaymentService<PayPalModel>
{
protected override void MakePayment(PayPalModel model)
{
//Implementation PayPalPayment
}
}
Payment Strategy
Here is the class that ties it all together. Its main purpose is to provide the selection functionality of the payment service based on the type of model passed. But unlike other examples here, it loosely couples the IPaymentService implementations so they are not directly referenced here. This means without changing the design, payment providers can be added or removed.
public class PaymentStrategy : IPaymentStrategy
{
private readonly IEnumerable<IPaymentService> paymentServices;
public PaymentStrategy(IEnumerable<IPaymentService> paymentServices)
{
this.paymentServices = paymentServices ?? throw new ArgumentNullException(nameof(paymentServices));
}
public void MakePayment<T>(T model) where T : IPaymentModel
{
GetPaymentService(model).MakePayment(model);
}
private IPaymentService GetPaymentService<T>(T model) where T : IPaymentModel
{
var result = paymentServices.FirstOrDefault(p => p.AppliesTo(model.GetType()));
if (result == null)
{
throw new InvalidOperationException(
$"Payment service for {model.GetType().ToString()} not registered.");
}
return result;
}
}
Usage
// I am showing this in code, but you would normally
// do this with your DI container in your composition
// root, and the instance would be created by injecting
// it somewhere.
var paymentStrategy = new PaymentStrategy(
new IPaymentService[]
{
new CreditCardPayment(), // <-- inject any dependencies here
new PayPalPayment() // <-- inject any dependencies here
});
// Then once it is injected, you simply do this...
var cc = new CreditCardModel() { CardHolderName = "Bob" /* Set other properties... */ };
paymentStrategy.MakePayment(cc);
// Or this...
var pp = new PayPalModel() { UserName = "Bob" /* Set other properties... */ };
paymentStrategy.MakePayment(pp);
Additional References:
Dependency Injection Unity - Conditional Resolving
Factory method with DI and IoC
This is one approach you could take. There's not a lot to go on from your source, and I'd really reconsider having MakePayment a void instead of something like an IPayResult.
public interface IPayModel { } // Worth investigating into common shared methods and properties for this
public interface IPaymentService
{
void MakePayment(IPayModel payModel);
}
public interface IPaymentService<T> : IPaymentService where T : IPayModel
{
void MakePayment(T payModel); // Void here? Is the status of the payment saved on the concrete pay model? Why not an IPayResult?
}
public class CreditCardModel : IPayModel
{
public string CardHolderName { get; set; }
}
public class PayPalModel : IPayModel
{
public string UserName { get; set; }
public string Password { get; set; }
}
public class CreditCardPayment : IPaymentService<CreditCardModel>
{
public void MakePayment(CreditCardModel payModel)
{
//Implmentation CreditCardPayment
}
void IPaymentService.MakePayment(IPayModel payModel)
{
MakePayment(payModel as CreditCardModel);
}
}
public class PayPalPayment : IPaymentService<PayPalModel>
{
public void MakePayment(PayPalModel payModel)
{
//Implmentation PayPalPayment
}
void IPaymentService.MakePayment(IPayModel payModel)
{
MakePayment(payModel as PayPalModel);
}
}
public enum PaymentType
{
PayPalPayment = 1,
CreditCardPayment = 2
}
So following your implementation approach, it could look something like:
static class Program
{
static void Main(object[] args)
{
IPaymentService paymentStrategy = null;
paymentStrategy = GetPaymentOption((PaymentType)1);
paymentStrategy.MakePayment(new PayPalModel { UserName = "", Password = "" });
paymentStrategy = GetPaymentOption((PaymentType)2);
paymentStrategy.MakePayment(new CreditCardModel { CardHolderName = "Aakash" });
Console.ReadLine();
}
private static IPaymentService GetPaymentOption(PaymentType paymentType)
{
switch (paymentType)
{
case PaymentType.PayPalPayment:
return new PayPalPayment();
case PaymentType.CreditCardPayment:
return new CreditCardPayment();
default:
throw new NotSupportedException($"Payment Type '{paymentType.ToString()}' Not Supported");
}
}
}
I also think for a strategy/factory pattern approach, manually creating an IPayModel type doesn't make much sense. Therefore you could expand the IPaymentService as an IPayModel factory:
public interface IPaymentService
{
IPayModel CreatePayModel();
void MakePayment(IPayModel payModel);
}
public interface IPaymentService<T> : IPaymentService where T : IPayModel
{
new T CreatePayModel();
void MakePayment(T payModel);
}
public class CreditCardPayment : IPaymentService<CreditCardModel>
{
public CreditCardModel CreatePayModel()
{
return new CreditCardModel();
}
public void MakePayment(CreditCardModel payModel)
{
//Implmentation CreditCardPayment
}
IPayModel IPaymentService.CreatePayModel()
{
return CreatePayModel();
}
void IPaymentService.MakePayment(IPayModel payModel)
{
MakePayment(payModel as CreditCardModel);
}
}
Usage would then be:
IPaymentService paymentStrategy = null;
paymentStrategy = GetPaymentOption((PaymentType)1);
var payModel = (PayPalModel)paymentStrategy.CreatePayModel();
payModel.UserName = "";
payModel.Password = "";
paymentStrategy.MakePayment(payModel);
Your code is basically using the factory pattern. This is a good way to handle more than one method of payment
http://www.dotnettricks.com/learn/designpatterns/factory-method-design-pattern-dotnet

Pass around an "AppendOnlyStringBuilder"

I have a serialization task where different parts and pieces of my object model know how to emit their own string segments, but I'd like the option to emit them using .Append against a common StringBuilder object. On the theory that we should not pass around our private objects for others to use indiscriminately, here's a class that wraps a StringBuilder to make it "append-only" for use in my scenario.
public sealed class AppendOnlyStringBuilder {
private readonly StringBuilder _stringBuilder;
public AppendOnlyStringBuilder(StringBuilder stringBuilder)
{
_stringBuilder = stringBuilder;
}
public AppendOnlyStringBuilder Append<T>(T value)
{
_stringBuilder.Append(value);
return this;
}
}
If my code inside of the different chunks of my model right now all look similar to this:
// Chunk1 class
public override string ToString() {
StringBuilder sb = new StringBuilder();
sb
.Append(_prop1.Value)
.Append(_prop2.Value)
.Append(_prop3.Value);
return sb.ToString();
}
And these ToString methods are called from the main routine's serialization method like so:
// MainObject class
Chunk1 _chunk1;
Chunk2 _chunk2;
Chunk3 _chunk3;
public override string ToString() {
StringBuilder sb = new StringBuilder();
sb
.Append(_chunk1.ToString()) // ToString may be unnecessary here
.Append(_chunk2.ToString())
.Append(_chunk3.ToString());
return sb.ToString();
}
How can I elegantly switch to passing around a single AppendOnlyStringBuilder for use in all these chunk classes instead of each one internally creating a new StringBuilder and doing ToString?
I'd like it to be used something like this:
// MainObject class
public override string ToString() {
StringBuilder sb = new StringBuilder();
AppendOnlyStringBuilder aosb = new AppendOnlyStringBuilder(sb);
aosb
.Append(_chunk1)
.Append(_chunk2)
.Append(_chunk3);
return sb.ToString();
}
An extension method is a natural way to get this syntax, but I'm running into problems due to the extension method needing to be static and thus not able to access private parts of the Chunk classes. I'd like to keep the same ToString in the chunk classes so they can still do their normal "serialize just me" thing, but I'd also like for them to be able to optionally append to my common AppendOnlyStringBuilder.
I guess I could do this:
_chunk1.AppendTo(aosb);
_chunk2.AppendTo(aosb);
_chunk3.AppendTo(aosb);
But something about that bugs me--I'd like to use a fluent interface that begins with the AppendOnlyStringBuilder object as in my example previously.
Ok, here goes:
using System.IO;
abstract class BaseClass
{
protected abstract void WriteToTextWriter(TextWriter textWriter);
public void SerializeTo(TextWriter textWriter)
{
WriteToTextWriter(textWriter);
}
public sealed override string ToString()
{
var writer = new StringWriter();
SerializeTo(writer);
return writer.ToString();
}
}
abstract class ChunkBase : BaseClass
{
private readonly string _index;
protected ChunkBase(string index)
{
_index = index;
}
protected sealed override void WriteToTextWriter(TextWriter textWriter)
{
textWriter.Write("Chunk");
textWriter.Write(_index);
}
}
class Chunk1 : ChunkBase { public Chunk1() : base("1") { } }
class Chunk2 : ChunkBase { public Chunk2() : base("2") { } }
class Chunk3 : ChunkBase { public Chunk3() : base("3") { } }
class ClassWithChunks : BaseClass
{
private readonly Chunk1 _chunk1 = new Chunk1();
private readonly Chunk2 _chunk2 = new Chunk2();
private readonly Chunk3 _chunk3 = new Chunk3();
protected override void WriteToTextWriter(TextWriter textWriter)
{
_chunk1.SerializeTo(textWriter);
_chunk2.SerializeTo(textWriter);
_chunk3.SerializeTo(textWriter);
}
}
Now, if you want chaining, you could do this:
class Chainable
{
private readonly TextWriter _textWriter;
public Chainable(TextWriter textWriter)
{
_textWriter = textWriter;
}
public Chainable Write(BaseClass obj)
{
obj.SerializeTo(_textWriter);
return this;
}
}
Then, your WriteToTextWriter could be, for example, this:
public override void WriteToTextWriter(TextWriter textWriter)
{
new Chainable(textWriter)
.Write(_chunk1)
.Write(_chunk2)
.Write(_chunk3);
}
I'm not sure it's worth it: the code is certainly cleaner, but it will be harder for someone (including your future self) to decipher, because of the additional layer of complexity.
Edit: Making the abstract method protected seems to add little here, but in production code, the extra layer could well be helpful. You'll want to add some switches, too, to handle formatting and the like.
Seems like the ideal candidate for the adapter pattern.
(untested code)
public interface IAppendOnly
{
void Append(string content);
}
public class AppendOnlyStringBuilder : IAppendOnly
{
private StringBuilder _stringBuilder = new StringBuilder()
public void Append(string content)
{
_stringBuilder.Append(content);
}
public override string ToString()
{
return _stringBuilder.ToString();
}
}
public class Chunk
{
public void AppendTo(IAppendOnly appendOnly)
{
appendOnly.Append("My Content");
}
}
Then each Chunk works without the knowledge of how the interface was instantiated:
_chunk1.AppendTo(aosb);
_chunk2.AppendTo(aosb);
_chunk3.AppendTo(aosb);
But something about that bugs me--I'd like to use a fluent interface that begins with the AppendOnlyStringBuilder object as in my example previously.
So with this requirement (minus the unnecessary AppendOnlyStringBuilder class) you'd then switch the interface direction.
public interface IGetString
{
string GetString();
}
public Chunk : IGetString
{
public string GetString()
{
return "MyContent";
}
}
public static class StringBuilderExtensions
{
public static StringBuilder AppendFrom(this StringBuilder instance
, IGetString getString)
{
instance.Append(getString.GetString())
return instance;
}
}
Then it's Fluent:
var sb = new StringBuilder;
var a = new Chunk();
var b = new Chunk();
sb.AppendFrom(a).AppendFrom(b);
If you want only one instatiated object of a type you could use the singleton pattern (Google will give you many exampels)
If you have a global object (something like a "myApplication"-class) you could offer this there.
Other way is a static class offering this singleton instance "from everywhere".
Your code would append directly to this one instance...
Hope this helps

Inheriting an already instantiated base object

Is it possible to do something like the following:
public class ChildClass : BaseClass
{
public ChildClass(BaseClass o)
{
base = o;
}
}
Basically, I want a transparent way to wrap a base class inside of other functionality. One example I've thought of is a custom Settings Provider which transparently audits the settings passed through it.
public class SettingsAuditor : SettingsProvider
{
public SettingsAuditor(SettingsProvider o)
{
base = o;
}
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals)
{
// Log the property change to a file
base.SetPropertyValues(context, propvals);
}
}
Then I could do the following:
mySettingsProvider = new SettingsAuditor(mySettingsProvider);
And all changes would go through the overridden SetPropertyValues before passing to the original object.
I could use a private SettingsProvider member, but then I either cannot inherit from SettingsProvider, or have an entire SettingsProvider (base) not being used at all.
I'm using C# 4.0 and .Net 4.0.
You cannot do base = o;
What you're looking for is the Decorator Pattern), which is a way to compositionally add functionality at runtime (vs. inheritance).
Instead of trying to set the base, you just contain the inner member. As long as the wrapper implements the same interface or base class as the inner object, you can pass back the new wrapper. You can wrap as many decorators as you want.
Consider:
public interface ICar
{
void Drive();
}
public class Car : ICar
{
public void Drive()
{
Console.WriteLine("vroom");
}
}
public class BuckleUp : ICar
{
ICar car;
public BuckleUp(ICar car) { this.car = car; }
public void Drive()
{
Console.WriteLine("click!");
car.Drive();
}
}
public class CheckMirrors : ICar
{
ICar car;
public CheckMirrors(ICar car) { this.car = car; }
public void Drive()
{
Console.WriteLine("mirrors adjusted");
car.Drive();
}
}
Now consider you have a method that accepts an ICar and tells it to drive. You could give it a Car, and it would work, but you could also wrap that car in a BuckleUp and a CheckMirrors and you wouldn't have to change that method at all. You've modified functionality through composition using the Decorator Pattern.
No. This looks like it should be a Composition vs Inheritance issue. You need to evaluate whether you are a "is a" or a "has a."
A little help for your journey
This is not a complete implmentation and it could probably be done much cleaner with expression trees... but this was a quick swing at faking AOP using DynamicObject with .Net 4.0.
public class MyDynamicWrapper<T> : DynamicObject
{
public T Wrapped { get; private set; }
public Action<T> Pre { get; private set; }
public Action<T> Post { get; private set; }
public MyDynamicWrapper(T wrapped, Action<T> pre, Action<T> post)
{
this.Wrapped = wrapped;
this.Pre = pre;
this.Post = post;
}
public override bool TryGetMember(
GetMemberBinder binder,
out object result)
{
var type = typeof(T);
var method = type.GetMethod(binder.Name);
if (method != null)
{
Func<object> func = () =>
{
if (Pre != null)
Pre(Wrapped);
// support for input parameters could be added here
var ret = method.Invoke(Wrapped, null);
if (Post != null)
Post(Wrapped);
return ret;
};
result = func;
return true;
}
return base.TryGetMember(binder, out result);
}
}
public class MyDynamicWrapper
{
public static MyDynamicWrapper<T> Create<T>(
T toWrap,
Action<T> pre = null,
Action<T> post = null)
{
return new MyDynamicWrapper<T>(toWrap, pre, post);
}
}
public class MyObject
{
public void MyMethod()
{
Console.WriteLine("Do Something");
}
}
class Program
{
static void Main()
{
var myobject = new MyObject();
dynamic mydyn = MyDynamicWrapper.Create(
myobject,
p => Console.WriteLine("before"),
p => Console.WriteLine("after"));
// Note that you have no intellisence...
// but you could use the old implmentation before you
// changed to this wrapped version.
mydyn.MyMethod();
/* output below
before
Do Something
after
*/
}
}
No, but you could fake it:
public class SettingsAuditor
{
SettingsProvider #base;
public SettingsAuditor(SettingsProvider o)
{
#base = o;
}
public void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals)
{
// Log the property change to a file
#base.SetPropertyValues(context, propvals);
}
}
Note here, #base isn't the actual base, just a varaible named base

Categories

Resources