在我目前的工作中,经常发生的事情是有一个通用的过程需要发生,但是该过程的奇数部分需要根据某个变量的值而稍有不同,所以我不是非常确定处理此问题的最优雅方法是什么。
我将使用我们通常使用的示例,该示例的处理方式会根据所处理的国家/地区而略有不同。
所以我有一堂课,我们称之为Processor
:
public class Processor
{
public string Process(string country, string text)
{
text.Capitalise();
text.RemovePunctuation();
text.Replace("é", "e");
var split = text.Split(",");
string.Join("|", split);
}
}
除了某些国家只需要采取其中一些行动。例如,只有6个国家需要资本化步骤。要分割的字符可能会因国家/地区而异。'e'
仅根据国家/地区,才需要替换重音符号。
显然,您可以通过执行以下操作来解决此问题:
public string Process(string country, string text)
{
if (country == "USA" || country == "GBR")
{
text.Capitalise();
}
if (country == "DEU")
{
text.RemovePunctuation();
}
if (country != "FRA")
{
text.Replace("é", "e");
}
var separator = DetermineSeparator(country);
var split = text.Split(separator);
string.Join("|", split);
}
但是,当您与世界上所有可能的国家打交道时,这将变得非常麻烦。而且无论如何,这些if
语句使逻辑更难以阅读(至少,如果您想象的是比示例更复杂的方法),并且循环复杂性开始迅速攀升。
所以目前我正在做这样的事情:
public class Processor
{
CountrySpecificHandlerFactory handlerFactory;
public Processor(CountrySpecificHandlerFactory handlerFactory)
{
this.handlerFactory = handlerFactory;
}
public string Process(string country, string text)
{
var handlers = this.handlerFactory.CreateHandlers(country);
handlers.Capitalier.Capitalise(text);
handlers.PunctuationHandler.RemovePunctuation(text);
handlers.SpecialCharacterHandler.ReplaceSpecialCharacters(text);
var separator = handlers.SeparatorHandler.DetermineSeparator();
var split = text.Split(separator);
string.Join("|", split);
}
}
处理程序:
public class CountrySpecificHandlerFactory
{
private static IDictionary<string, ICapitaliser> capitaliserDictionary
= new Dictionary<string, ICapitaliser>
{
{ "USA", new Capitaliser() },
{ "GBR", new Capitaliser() },
{ "FRA", new ThingThatDoesNotCapitaliseButImplementsICapitaliser() },
{ "DEU", new ThingThatDoesNotCapitaliseButImplementsICapitaliser() },
};
// Imagine the other dictionaries like this...
public CreateHandlers(string country)
{
return new CountrySpecificHandlers
{
Capitaliser = capitaliserDictionary[country],
PunctuationHanlder = punctuationDictionary[country],
// etc...
};
}
}
public class CountrySpecificHandlers
{
public ICapitaliser Capitaliser { get; private set; }
public IPunctuationHanlder PunctuationHanlder { get; private set; }
public ISpecialCharacterHandler SpecialCharacterHandler { get; private set; }
public ISeparatorHandler SeparatorHandler { get; private set; }
}
同样,我不确定自己是否喜欢。逻辑仍然被所有工厂创建所掩盖,例如,您不能简单地查看原始方法并查看执行“ GBR”过程时会发生什么。您还最终以这种方式创建了许多类(在比这更复杂的示例中)GbrPunctuationHandler
,UsaPunctuationHandler
等等......这意味着你必须在几个不同的类别看,以计算出所有标点期间可能发生的可能采取的行动处理。显然,我不希望一个拥有十亿个if
语句的巨型类,但同样地,逻辑略有不同的20个类也感到笨拙。
基本上,我认为我已经陷入某种OOP的纠结中,并且还不太了解解决纠缠的好方法。我想知道是否有某种模式可以帮助此类流程?
if (country == "DEU")
您检查if (config.ShouldRemovePunctuation)
。
country
使用字符串而不是模拟这些选择的类的实例?
PreProcess
功能,可以根据某些国家/地区以不同的方式实施,DetermineSeparator
可以针对所有国家/地区使用,还有一个PostProcess
。所有这些都可以protected virtual void
使用默认实现,然后您可以针对Processors
每个国家/地区