在接口的多种实现中违反SOLID原则 [英] Breaking SOLID Principles in multiple implementation of an Interface
问题描述
我在factory
方法中面临依赖倒置的问题,它也打破了开放式封闭原则.我的代码看起来像下面的代码
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();
}
}
}
现在的问题是Factory
类违反了开放式封闭原则,因此它也违反了依赖倒置原则
Now the problem is the Factory
class is breaking Open closed principle so it also breakes Dependency Inversion Principle
然后
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);
}
}
由于上面的工厂类打破了依赖倒置,我删除了Factory
类,并更改了SaveDataFlow
类,如下所示:
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);
}
}
}
并使用Unity Framework解决了这些依赖关系
And resolved those dependencies using Unity Framework
container.RegisterType<IWriter, DBWriter>("DB");
container.RegisterType<IWriter, FileWriter>("FILE");
但是,最终我最终打破了开放式封闭原则. 我需要更好的设计/解决方案来解决此类问题,但我必须遵循SOLID原则.
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)
{
}
}
}
您可以根据需要拥有任意数量的IWriter
,只需注册它们即可:
You can have as many IWriter
s as you want, just register them:
container.RegisterType<IWriter, LogWriter>("log");
如果您愿意,甚至可以在编写器上实现装饰器.
You can even implement decorators over the writers if you want as well.
您使用(错误命名的)IWriterSelector
作为如何选择作家的实现,这应该只涉及获得作家! throw
异常在这里非常有用,如果没有适合您需要的实现,它将很快失败!
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!!
如果您遇到Open Closed
问题,请使用策略"或模板"模式来克服.
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>();
这篇关于在接口的多种实现中违反SOLID原则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!