Şu anki işimde çok fazla ortaya çıkan bir şey, gerçekleşmesi gereken genelleştirilmiş bir süreç olduğu, ancak o zaman bu sürecin garip kısmının belirli bir değişkenin değerine bağlı olarak biraz farklı olması gerekiyor ve ben değilim bununla başa çıkmanın en zarif yolunun ne olduğundan emin.
Genelde sahip olduğumuz, üzerinde çalıştığımız ülkeye bağlı olarak işleri biraz farklı yapan örneği kullanacağım.
Bir dersim var, diyelim ki 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);
}
}
Ancak bu eylemlerin sadece bir kısmının belirli ülkeler için yapılması gerekir. Örneğin, yalnızca 6 ülke kapitalizasyon adımına ihtiyaç duymaktadır. Bölünecek karakter ülkeye bağlı olarak değişebilir. Aksanlı olanların değiştirilmesi 'e'
yalnızca ülkeye bağlı olarak gerekebilir.
Açıkçası böyle bir şey yaparak çözebilirsiniz:
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);
}
Ancak dünyadaki tüm olası ülkelerle uğraşırken, bu çok hantal hale gelir. Ve ne olursa olsun, if
ifadeler mantığı okumayı zorlaştırır (en azından örnekten daha karmaşık bir yöntem hayal ediyorsanız) ve siklomatik karmaşıklık oldukça hızlı bir şekilde kaymaya başlar.
Şu anda böyle bir şey yapıyorum:
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);
}
}
Eylemciler:
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; }
}
Hangi eşit sevmiyorum gerçekten emin değilim. Mantık hala tüm fabrika oluşturma işlemleri tarafından gizlenmiştir ve örneğin orijinal yönteme bakamaz ve örneğin bir "GBR" işlemi yürütüldüğünde ne olacağını göremezsiniz. Ayrıca tarzında (bundan daha karmaşıktır örneklerde), birçok sınıfı oluşturma sonunda GbrPunctuationHandler
, UsaPunctuationHandler
noktalama işaretsiz sırasında olabilirdi olası tüm işlemleri dışarı şekil için birkaç farklı sınıflara bakmak zorunda olduğunu hangi araçlar ... vb, taşıma. Açıkçası if
, milyarlarca ifadeye sahip dev bir sınıf istemiyorum , ama aynı derecede biraz farklı mantığa sahip 20 sınıf da tıknaz hissediyor.
Temelde kendimi bir çeşit OOP düğümüne aldım ve onu çözmek için iyi bir yol bilmiyorum. Orada bu tür işlemlere yardımcı olacak bir model olup olmadığını merak ediyordum.
if (country == "DEU")
kontrol edin if (config.ShouldRemovePunctuation)
.
country
bir dize yerine bir sınıf modelleyen bu seçenekler örneğidir?
PreProcess
göre, bazı ülkelere göre farklı şekilde uygulanabilen bir işlevsellikDetermineSeparator
var, hepsi için orada olabilir ve aPostProcess
. Hepsiprotected virtual void
varsayılan bir uygulama ile olabilir ve daha sonraProcessors
her ülke için belirli olabilir