对于我正在进行的项目,我需要使用不同的源数据格式创建对象,或多或少是这样的:
public class FooService
{
protected DataFormat Format { get; set; }
public FooService(DataFormat format = DataFormat.Json)
{
Format = format;
}
public Foo GetFoo(int id)
{
string content = GetContentInFormat("someuri/foo/" + id, Format);
// Something here must create a "Foo" object
// based on Format, which could be Json, Xml or other
}
}
public enum DataFormat
{
Json,
Xml
}
我知道我可以:
1)使用不同的方法并根据格式选择正确的方法:
switch (Format)
{
case DataFormat.Xml:
return CreateFooFromXml(content);
case DataFormat.Json:
return CreateFooFromJson(content);
default:
throw new Exception("Invalid format.");
}
缺点:将会以这种方式创建至少8种不同类型,因此我需要更具可扩展性和可维护性的东西。
2)使FooService成为一个接口或抽象类,并实现具体的类,每种格式一个。
缺点: 所有类中的业务逻辑总是是相同的,除了类实例化。 JsonFooService
和XmlFooService
可能令人困惑。
我想从可扩展性和可维护性的角度来了解什么是最佳解决方案。
答案 0 :(得分:3)
您可以将其设为接口(IFormat
)。
然后,对于每种格式,创建一个实现JsonFormat
的具体类(例如IFormat
)。
每个具体类应该只包含特定格式的唯一内容,例如如何找到给定Id
的元素/记录。
答案 1 :(得分:2)
你在这里清楚地说creational patterns,但我认为我们不太了解Foo的复杂性,而是明确地推荐一个人。幸运的是,没有那么多的GoF创作模式,所以你可以在相当短的时间内阅读所有这些模式。您似乎已经了解了factory-method模式,因此您可以跳到abstract factory和builder,看看它们是否更符合要求。
构建器维基的提示:
- Builder专注于逐步构建复杂对象。 Abstract Factory强调一系列产品对象(简单 或复杂的)。 Builder返回产品作为最后一步,但到目前为止 就抽象工厂而言,产品会被退回 立即
- 构建器通常会构建Composite。
- 通常,设计开始使用工厂方法(不太复杂,可定制,子类扩散)并向Abstract发展 Factory,Prototype或Builder(更灵活,更复杂) 设计师发现需要更多灵活性的地方。
- 有时创建模式是互补的:Builder可以使用其他模式之一来实现构建哪些组件。 抽象工厂,构建器和Prototype可以在其中使用Singleton 的实施方式。
- 构建者是fluent interface的合适人选。
希望有所帮助。
答案 2 :(得分:1)
这是strategy pattern的典型用例,它处理可在运行时选择的算法。可以将switch-cases和long if / else if / else条件转换为优雅的可维护代码
如果您想动态切换数据格式生成器,可以查看MEF等选项,这是扩展应用程序以发现新扩展而无需任何配置的方法
答案 3 :(得分:0)
具体来说,你可以使用IOC(例如autofac)和某种类型的注射(因为我看到你已经接近这种想法),
在启动时注册所有可用的格式服务
(从配置或简单的一次性初始化,随着时间的推移,当您添加新类型时,易于维护)...
例如,实现IOutputFormatService接口
然后,您可以动态舍入它们(例如,解析,列出所有已实现的格式)
并且每个人都可以做这项工作'通过通用界面 - 或者如果您了解它们'你也可以专门访问它们,如果需要的话,比如IJsonOutputFormatInterface
如果/当您添加(或删除)新的时 - 它只是更改的配置部分
正如其他人所提到的,您只需要对每个服务进行编码,以便对其进行特定的处理,格式化渲染等
注意:不需要反思,它更像是一个重要的概念
答案 4 :(得分:0)
模式工厂方法就是你想要的。模式本身不会删除switch
语句,但它只存在于一个地方。
但是,您可以将模式与一些反射组合以删除switch语句。
代码(伪代码)
public class FormatterFactory
{
Dictionary<string, IFormatter> _formatters;
public void FormatterFactory()
{
var baseType = typeof(IFormatter);
var formatterTypes = AppDomain
.GetExecutingAssembly()
.GetTypes.Where(x=>baseType.IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract);
// convention based. Each formatter must be named like "JsonFormatter"
foreach (var type in formatterTypes)
{
_formatters.Add(type.Name.Replace("Formatter", "").ToLower(), type),
}
}
public IFormatter Create(string formatName)
{
var type = _formatters[formatName.ToLower());
return (IFormatter)Activator.CreateInstance(type);
}
}
用法:
var factory = new FormatterFactory();
var json = factory.Create("json").Serialize(myObject);