Was in meiner aktuellen Arbeit ziemlich häufig vorkommt, ist, dass ein verallgemeinerter Prozess stattfinden muss, aber dann muss der seltsame Teil dieses Prozesses je nach Wert einer bestimmten Variablen etwas anders ablaufen, und das bin ich nicht Ich bin mir ziemlich sicher, was der eleganteste Weg ist, damit umzugehen.
Ich werde das Beispiel verwenden, das wir normalerweise haben und das die Dinge je nach Land, mit dem wir es zu tun haben, etwas anders macht.
Also habe ich eine Klasse, nennen wir es 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);
}
}
Abgesehen davon, dass nur einige dieser Maßnahmen für bestimmte Länder durchgeführt werden müssen. Beispielsweise benötigen nur 6 Länder den Kapitalisierungsschritt. Der zu teilende Charakter kann sich je nach Land ändern. Akzent ersetzen'e'
möglicherweise nur je nach Land erforderlich.
Offensichtlich könnten Sie es lösen, indem Sie so etwas tun:
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);
}
Aber wenn Sie mit allen möglichen Ländern der Welt zu tun haben, wird das sehr umständlich. Und trotzdem dieif
erschweren Anweisungen das Lesen der Logik (zumindest, wenn Sie sich eine komplexere Methode als das Beispiel vorstellen), und die zyklomatische Komplexität steigt ziemlich schnell an.
Im Moment mache ich so etwas:
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);
}
}
Handler:
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; }
}
Was ich auch nicht wirklich sicher bin, ob ich es mag. Die Logik wird durch die gesamte Factory-Erstellung immer noch etwas verdeckt, und Sie können nicht einfach die ursprüngliche Methode betrachten und sehen, was passiert, wenn beispielsweise ein "GBR" -Prozess ausgeführt wird. Sie landen auch viele Klassen zu schaffen (in komplexeren Beispielen als diese) im Stil GbrPunctuationHandler
, UsaPunctuationHandler
etc ... was bedeutet , dass Sie aus allen möglichen Aktionen an mehreren verschiedenen Klassen Abbildung aussehen müssen , die während der Zeichensetzung passieren könnte Handhabung. Offensichtlich will ich keine Riesenklasse mit einer Milliardeif
Aussagen, aber ebenso 20 Klassen mit leicht unterschiedlicher Logik fühlen sich auch klobig an.
Grundsätzlich denke ich, dass ich mich in eine Art OOP-Knoten verwickelt habe und keine gute Möglichkeit kenne, ihn zu entwirren. Ich habe mich gefragt, ob es da draußen ein Muster gibt, das bei dieser Art von Prozess helfen würde.
if (country == "DEU")
Sie zu überprüfen if (config.ShouldRemovePunctuation)
.
country
eine Zeichenfolge eher eine Instanz einer Klasse, die diese Optionen modelliert?
PreProcess
Funktionalität, die je nach Land unterschiedlich implementiert werden könnte,DetermineSeparator
für alle verfügbar sein kann, und aPostProcess
. Alle von ihnen könnenprotected virtual void
mit einer Standardimplementierung sein, und dann können Sie spezifischeProcessors
pro Land haben