在我目前的工作中,经常发生的事情是有一个通用的过程需要发生,但是该过程的奇数部分需要根据某个变量的值而稍有不同,所以我不是非常确定处理此问题的最优雅方法是什么。
我将使用我们通常使用的示例,该示例在做事时会有所不同,具体取决于所处理的国家/地区。
所以我有一堂课,我们称之为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);
}
}
Run Code Online (Sandbox Code Playgroud)
除了某些国家只需要采取其中一些行动。例如,只有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);
}
Run Code Online (Sandbox Code Playgroud)
但是,当您与世界上所有可能的国家打交道时,这将变得非常麻烦。而且无论如何,这些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);
}
}
Run Code Online (Sandbox Code Playgroud)
处理程序:
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; }
}
Run Code Online (Sandbox Code Playgroud)
同样,我不确定自己是否喜欢。逻辑仍然被所有工厂创建所模糊,例如,您不能简单地查看原始方法并查看执行“ GBR”过程时会发生什么。您也结束了(在比这更复杂的例子),在风格造就了不少的班GbrPunctuationHandler
,UsaPunctuationHandler
等等......这意味着你必须在几个不同的类别看,以计算出所有标点期间可能发生的可能采取的行动处理。显然,我不希望一个拥有十亿个if
语句的巨型类,但同样地,逻辑略有不同的20个类也感到笨拙。
基本上,我认为我已经陷入某种OOP纠结,并且还不太了解解决纠缠的好方法。我想知道是否有某种模式可以帮助此类流程?
Mic*_*zyn 50
I would suggest encapsulating all options in one class:
public class ProcessOptions
{
public bool Capitalise { get; set; }
public bool RemovePunctuation { get; set; }
public bool Replace { get; set; }
public char ReplaceChar { get; set; }
public char ReplacementChar { get; set; }
public char JoinChar { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
and pass it into the Process
method:
public string Process(ProcessOptions options, string text)
{
if(options.Capitalise)
text.Capitalise();
if(options.RemovePunctuation)
text.RemovePunctuation();
if(options.Replace)
text.Replace(options.ReplaceChar, options.ReplacementChar);
var split = text.Split(options.SplitChar);
string.Join(options.JoinChar, split);
}
Run Code Online (Sandbox Code Playgroud)
Dam*_*ver 24
当.NET框架着手处理这类问题时,它并没有将所有模型都建模为string
。例如,您拥有CultureInfo
类:
提供有关特定区域性的信息(称为非托管代码开发的区域设置)。该信息包括区域性的名称,书写系统,使用的日历,字符串的排序顺序以及日期和数字的格式。
Now, this class may not contain the specific features that you need, but you can obviously create something analogous. And then you change your Process
method:
public string Process(CountryInfo country, string text)
Run Code Online (Sandbox Code Playgroud)
Your CountryInfo
class can then have a bool RequiresCapitalization
property, etc, that helps your Process
method direct its processing appropriately.
Cor*_*ane 12
也许Processor
每个国家可以有一个?
public class FrProcessor : Processor {
protected override string Separator => ".";
protected override string ProcessSpecific(string text) {
return text.Replace("é", "e");
}
}
public class UsaProcessor : Processor {
protected override string Separator => ",";
protected override string ProcessSpecific(string text) {
return text.Capitalise().RemovePunctuation();
}
}
Run Code Online (Sandbox Code Playgroud)
一个基类来处理处理的常见部分:
public abstract class Processor {
protected abstract string Separator { get; }
protected virtual string ProcessSpecific(string text) { }
private string ProcessCommon(string text) {
var split = text.Split(Separator);
return string.Join("|", split);
}
public string Process(string text) {
var s = ProcessSpecific(text);
return ProcessCommon(s);
}
}
Run Code Online (Sandbox Code Playgroud)
另外,您应该重新处理您的返回类型,因为它在编写它们时不会编译-有时某个string
方法不会返回任何内容。
You can create a common interface with a Process
method...
public interface IProcessor
{
string Process(string text);
}
Run Code Online (Sandbox Code Playgroud)
Then you implement it for each country...
public class Processors
{
public class GBR : IProcessor
{
public string Process(string text)
{
return $"{text} (processed with GBR rules)";
}
}
public class FRA : IProcessor
{
public string Process(string text)
{
return $"{text} (processed with FRA rules)";
}
}
}
Run Code Online (Sandbox Code Playgroud)
You can then create a common method for instantiating and executing each country related class...
// also place these in the Processors class above
public static IProcessor CreateProcessor(string country)
{
var typeName = $"{typeof(Processors).FullName}+{country}";
var processor = (IProcessor)Assembly.GetAssembly(typeof(Processors)).CreateInstance(typeName);
return processor;
}
public static string Process(string country, string text)
{
var processor = CreateProcessor(country);
return processor?.Process(text);
}
Run Code Online (Sandbox Code Playgroud)
Then you just need to create and use the processors like so...
// create a processor object for multiple use, if needed...
var processorGbr = Processors.CreateProcessor("GBR");
Console.WriteLine(processorGbr.Process("This is some text."));
// create and use a processor for one-time use
Console.WriteLine(Processors.Process("FRA", "This is some more text."));
Run Code Online (Sandbox Code Playgroud)
Here's a working dotnet fiddle example...
您将所有特定于国家/地区的处理置于每个国家/地区类别中。为所有实际的单个方法创建一个通用类(在Processing类中),因此每个国家/地区处理器将成为其他通用调用的列表,而不是在每个国家/地区类中复制代码。
注意:您需要添加...
using System.Assembly;
Run Code Online (Sandbox Code Playgroud)
为了使静态方法能够创建国家/地区类的实例。
归档时间: |
|
查看次数: |
2983 次 |
最近记录: |