Sesuatu yang muncul cukup banyak dalam pekerjaan saya saat ini adalah bahwa ada proses umum yang perlu terjadi, tetapi kemudian bagian aneh dari proses itu perlu terjadi sedikit berbeda tergantung pada nilai variabel tertentu, dan saya tidak cukup yakin apa cara paling elegan untuk menangani ini.
Saya akan menggunakan contoh yang biasanya kita miliki, yang melakukan hal-hal yang sedikit berbeda tergantung pada negara yang kita hadapi.
Jadi saya punya kelas, sebut saja 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);
}
}
Kecuali bahwa hanya beberapa tindakan yang perlu terjadi untuk negara-negara tertentu. Misalnya, hanya 6 negara yang memerlukan langkah kapitalisasi. Karakter untuk dibagi mungkin berubah tergantung pada negara. Mengganti aksen 'e'mungkin hanya diperlukan tergantung pada negara.
Jelas Anda bisa menyelesaikannya dengan melakukan sesuatu seperti ini:
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);
}
Tetapi ketika Anda berurusan dengan semua negara yang mungkin ada di dunia, itu menjadi sangat rumit. Dan terlepas dari itu, ifpernyataan membuat logika lebih sulit untuk dibaca (setidaknya, jika Anda membayangkan metode yang lebih kompleks daripada contoh), dan kompleksitas siklomatik mulai merayap cukup cepat.
Jadi saat ini saya sedang melakukan sesuatu seperti ini:
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);
}
}
Penangan:
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; }
}
Yang sama saya tidak yakin saya suka. Logikanya masih agak dikaburkan oleh semua pembuatan pabrik dan Anda tidak bisa begitu saja melihat metode asli dan melihat apa yang terjadi ketika proses "GBR" dijalankan, misalnya. Anda juga akhirnya menciptakan banyak kelas (dalam contoh yang lebih kompleks dari ini) dalam gaya GbrPunctuationHandler,, UsaPunctuationHandlerdll ... yang berarti Anda harus melihat beberapa kelas yang berbeda untuk mencari tahu semua tindakan yang mungkin bisa terjadi selama tanda baca penanganan. Jelas saya tidak ingin satu kelas raksasa dengan satu miliar ifpernyataan, tetapi sama-sama 20 kelas dengan logika yang sedikit berbeda juga terasa kikuk.
Pada dasarnya saya pikir saya telah mendapatkan semacam simpul OOP dan tidak tahu cara yang baik untuk menguraikannya. Saya bertanya-tanya apakah ada pola di luar sana yang akan membantu dengan jenis proses ini?
if (country == "DEU")Anda periksa if (config.ShouldRemovePunctuation).
countrysebuah string yang bukan sebuah instance dari kelas yang model orang-orang pilihan?
PreProcessfungsi, yang dapat diimplementasikan secara berbeda berdasarkan pada beberapa negara,DetermineSeparatordapat ada untuk mereka semua, dan aPostProcess. Semuanya dapatprotected virtual voiddengan implementasi default, dan kemudian Anda dapat memiliki spesifikProcessorsper negara