สิ่งที่เกิดขึ้นค่อนข้างมากในงานปัจจุบันของฉันคือมีกระบวนการทั่วไปที่ต้องเกิดขึ้น แต่แล้วส่วนแปลก ๆ ของกระบวนการนั้นต้องเกิดขึ้นแตกต่างกันเล็กน้อยขึ้นอยู่กับค่าของตัวแปรบางตัวและฉันไม่ ค่อนข้างแน่ใจว่าเป็นวิธีที่ดีที่สุดในการจัดการกับสิ่งนี้
ฉันจะใช้ตัวอย่างที่เรามักจะมีซึ่งกำลังทำสิ่งแตกต่างกันเล็กน้อยขึ้นอยู่กับประเทศที่เรากำลังเผชิญอยู่
ดังนั้นฉันมีชั้นเรียนลองเรียกมันว่า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 คลาสที่มีตรรกะต่างกันเล็กน้อยก็รู้สึกว่า clunky
โดยทั่วไปฉันคิดว่าฉันมีตัวเองเป็นปม OOP และไม่ทราบวิธีที่ดีในการแก้มัน ฉันสงสัยว่ามีรูปแบบที่จะช่วยกระบวนการประเภทนี้หรือไม่
if (country == "DEU")
if (config.ShouldRemovePunctuation)
country
PreProcess
ฟังก์ชั่นที่สามารถดำเนินการที่แตกต่างกันขึ้นอยู่กับบางส่วนของประเทศที่สามารถจะมีสำหรับพวกเขาทั้งหมดและDetermineSeparator
PostProcess
ทั้งหมดนี้สามารถprotected virtual void
เริ่มต้นได้จากการใช้งานและจากนั้นคุณสามารถระบุได้เฉพาะProcessors
ประเทศ