การเขียนโปรแกรมเชิงวัตถุ - วิธีการหลีกเลี่ยงการทำซ้ำในกระบวนการที่แตกต่างกันเล็กน้อยขึ้นอยู่กับตัวแปร


64

สิ่งที่เกิดขึ้นค่อนข้างมากในงานปัจจุบันของฉันคือมีกระบวนการทั่วไปที่ต้องเกิดขึ้น แต่แล้วส่วนแปลก ๆ ของกระบวนการนั้นต้องเกิดขึ้นแตกต่างกันเล็กน้อยขึ้นอยู่กับค่าของตัวแปรบางตัวและฉันไม่ ค่อนข้างแน่ใจว่าเป็นวิธีที่ดีที่สุดในการจัดการกับสิ่งนี้

ฉันจะใช้ตัวอย่างที่เรามักจะมีซึ่งกำลังทำสิ่งแตกต่างกันเล็กน้อยขึ้นอยู่กับประเทศที่เรากำลังเผชิญอยู่

ดังนั้นฉันมีชั้นเรียนลองเรียกมันว่า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 และไม่ทราบวิธีที่ดีในการแก้มัน ฉันสงสัยว่ามีรูปแบบที่จะช่วยกระบวนการประเภทนี้หรือไม่


ดูเหมือนว่าคุณมีPreProcessฟังก์ชั่นที่สามารถดำเนินการที่แตกต่างกันขึ้นอยู่กับบางส่วนของประเทศที่สามารถจะมีสำหรับพวกเขาทั้งหมดและDetermineSeparator PostProcessทั้งหมดนี้สามารถprotected virtual voidเริ่มต้นได้จากการใช้งานและจากนั้นคุณสามารถระบุได้เฉพาะProcessorsประเทศ
Icepickle

งานของคุณคือทำในกรอบเวลาที่กำหนดสิ่งที่ใช้งานได้และสามารถรักษาในอนาคตอันใกล้โดยคุณหรือคนอื่น หากมีตัวเลือกหลายตัวที่สามารถตอบสนองเงื่อนไขทั้งสองนี้คุณสามารถเลือกได้ตามใจชอบ
Dialecticus

2
ตัวเลือกที่ทำงานได้สำหรับคุณคือการกำหนดค่า ดังนั้นในรหัสของคุณคุณไม่ได้ตรวจสอบประเทศที่เฉพาะเจาะจง แต่สำหรับตัวเลือกการกำหนดค่าเฉพาะ แต่แต่ละประเทศจะมีชุดตัวเลือกการกำหนดค่าเฉพาะเหล่านั้น ยกตัวอย่างเช่นแทนที่จะให้คุณตรวจสอบif (country == "DEU") if (config.ShouldRemovePunctuation)
Dialecticus

11
หากประเทศมีตัวเลือกต่างๆทำไมสตริงมากกว่าเป็นตัวอย่างของการเรียนว่ารูปแบบตัวเลือกเหล่านั้นหรือไม่ country
Damien_The_Unbeliever

@Damien_The_Unbeliever - คุณช่วยเพิ่มรายละเอียดหน่อยได้ไหม? คำตอบของ Robert Brautigam ด้านล่างเป็นไปตามสิ่งที่คุณแนะนำหรือไม่ - อ่าเห็นคำตอบของคุณแล้วขอบคุณ!
John Darvill

คำตอบ:


53

ฉันขอแนะนำให้ห่อหุ้มตัวเลือกทั้งหมดในชั้นเดียว:

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; }
  public char SplitChar { get; set; }
}

และผ่านเข้าไปในProcessวิธีการ:

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);
}

4
ไม่แน่ใจว่าทำไมบางสิ่งบางอย่างเช่นนี้จึงไม่ได้ลองมาก่อนที่จะกระโดดCountrySpecificHandlerFactory... o_0
Mateen Ulhaq

ตราบใดที่ไม่มีตัวเลือกพิเศษเกินไปฉันก็จะไปทางนี้แน่นอน หากตัวเลือกต่าง ๆ ถูกต่อเนื่องเป็นไฟล์ข้อความมันยังช่วยให้ผู้ที่ไม่ใช่โปรแกรมเมอร์สามารถกำหนดตัวแปรใหม่ / ปรับปรุงตัวเลือกที่มีอยู่โดยไม่จำเป็นต้องเปลี่ยนเป็นแอปพลิเคชัน
ทอม

4
นั่นpublic class ProcessOptionsน่าจะเป็น[Flags] enum class ProcessOptions : int { ... }...
Drunken Code Monkey

ProcessOptionsและผมคิดว่าถ้าพวกเขาต้องการพวกเขาจะมีแผนที่ของประเทศกับ สะดวกมาก.
theonlygusti

24

เมื่อกรอบ NET stringออกไปจัดการกับทุกประเภทของปัญหาเหล่านี้ก็ทำทุกอย่างไม่ได้เป็นรูปแบบ ตัวอย่างเช่นคุณมีCultureInfoคลาส :

ให้ข้อมูลเกี่ยวกับวัฒนธรรมเฉพาะ (เรียกว่าโลแคลสำหรับการพัฒนาโค้ดที่ไม่มีการจัดการ) ข้อมูลรวมถึงชื่อของวัฒนธรรมระบบการเขียนปฏิทินที่ใช้ลำดับการเรียงของสตริงและการจัดรูปแบบสำหรับวันที่และตัวเลข

ตอนนี้คลาสนี้อาจไม่มีคุณสมบัติเฉพาะที่คุณต้องการ แต่คุณสามารถสร้างบางสิ่งที่คล้ายคลึงกันได้ จากนั้นคุณเปลี่ยนProcessวิธีการของคุณ:

public string Process(CountryInfo country, string text)

CountryInfoชั้นเรียนของคุณสามารถมีbool RequiresCapitalizationคุณสมบัติ ฯลฯ ซึ่งจะช่วยให้Processวิธีการของคุณควบคุมการประมวลผลได้อย่างเหมาะสม


13

บางทีคุณอาจมีหนึ่ง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();
    }
}

และคลาสฐานหนึ่งเพื่อจัดการส่วนทั่วไปของการประมวลผล:

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);
    }
}

นอกจากนี้คุณควรปรับปรุงประเภทการส่งคืนของคุณเนื่องจากมันจะไม่คอมไพล์ในขณะที่คุณเขียนพวกเขา - บางครั้งstringวิธีการที่จะไม่ส่งกลับอะไร


ฉันเดาว่าฉันกำลังพยายามติดตามองค์ประกอบมากกว่ามนต์มรดก แต่ใช่มันเป็นตัวเลือกแน่นอนขอบคุณสำหรับการตอบกลับ
John Darvill

ยุติธรรมพอสมควร ฉันคิดว่าการสืบทอดมีความชอบธรรมในบางกรณี แต่ขึ้นอยู่กับว่าคุณวางแผนที่จะโหลด / จัดเก็บ / เรียกใช้ / เปลี่ยนวิธีการและการประมวลผลของคุณในท้ายที่สุด
Corentin Pane

3
บางครั้งการสืบทอดเป็นเครื่องมือที่เหมาะสมสำหรับงาน หากคุณมีกระบวนการที่จะทำงานในส่วนใหญ่เป็นแบบเดียวกับที่อยู่ในสถานการณ์ที่แตกต่างกัน แต่ยังมีหลายส่วนที่จะทำงานแตกต่างกันในสถานการณ์ที่แตกต่างกันว่าเป็นสัญญาณที่ดีคุณควรพิจารณาใช้มรดก
แทนเนอร์ Swett

5

คุณสามารถสร้างอินเตอร์เฟสทั่วไปด้วยProcessเมธอด ...

public interface IProcessor
{
    string Process(string text);
}

จากนั้นคุณใช้มันสำหรับแต่ละประเทศ ...

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)";
        }
    }
}

จากนั้นคุณสามารถสร้างวิธีการทั่วไปสำหรับการสร้างอินสแตนซ์และดำเนินการแต่ละคลาสที่เกี่ยวข้องกับประเทศ ...

// 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);
}

จากนั้นคุณเพียงแค่ต้องสร้างและใช้ตัวประมวลผลเช่นนั้น ...

// 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."));

นี่คือตัวอย่างซอดอทเน็ตที่ใช้งานได้ ...

คุณทำการประมวลผลเฉพาะประเทศทั้งหมดในแต่ละชั้นประเทศ สร้างคลาสทั่วไป (ในคลาสการประมวลผล) สำหรับแต่ละวิธีจริงดังนั้นตัวประมวลผลแต่ละประเทศจึงกลายเป็นรายการของการโทรทั่วไปอื่น ๆ แทนที่จะคัดลอกรหัสในแต่ละคลาสประเทศ

หมายเหตุ:คุณจะต้องเพิ่ม ...

using System.Assembly;

เพื่อให้วิธีการคงที่เพื่อสร้างตัวอย่างของระดับประเทศ


การสะท้อนกลับไม่ช้าอย่างน่าทึ่งเมื่อเปรียบเทียบกับรหัสที่ไม่มีการสะท้อน? มันคุ้มค่าสำหรับกรณีนี้หรือไม่?
jlvaquero

@ jlvaquero ไม่การสะท้อนนั้นไม่ได้ช้าอย่างน่าทึ่งเลย แน่นอนว่ามันมีประสิทธิภาพมากกว่าการระบุประเภทในขณะออกแบบ แต่มันเป็นความแตกต่างของประสิทธิภาพที่ไม่สำคัญและจะสังเกตได้ก็ต่อเมื่อคุณใช้งานมากเกินไป ฉันใช้ระบบการส่งข้อความขนาดใหญ่ที่สร้างขึ้นโดยใช้การจัดการวัตถุทั่วไปและเราไม่มีเหตุผลที่จะถามคำถามเกี่ยวกับประสิทธิภาพเลยและนั่นก็คือปริมาณงานจำนวนมหาศาล ไม่มีความแตกต่างที่เห็นได้ชัดเจนในประสิทธิภาพการทำงานฉันจะไปกับการรักษารหัสง่าย ๆ เช่นนี้
Reinstate Monica Cellio

หากคุณสะท้อนคุณจะไม่ต้องการลบสตริงประเทศออกจากการโทรแต่ละครั้งProcessและใช้ครั้งเดียวเพื่อรับ IProcessor ที่ถูกต้องแทน โดยทั่วไปคุณจะประมวลผลข้อความจำนวนมากตามกฎของประเทศเดียวกัน
Davislor

@Davislor นั่นคือสิ่งที่รหัสนี้ทำ เมื่อคุณเรียกProcess("GBR", "text");มันจะเรียกใช้งานเมธอดสแตติกที่สร้างอินสแตนซ์ของตัวประมวลผล GBR และดำเนินการเมธอดกระบวนการที่ มันรันเพียงครั้งเดียวสำหรับประเภทประเทศนั้น ๆ
Reinstate Monica Cellio

@Archer Right ดังนั้นในกรณีทั่วไปที่คุณกำลังประมวลผลหลาย ๆ สายตามกฎของประเทศเดียวกันมันจะมีประสิทธิภาพมากกว่าในการสร้างอินสแตนซ์หนึ่งครั้ง - หรือค้นหาอินสแตนซ์คงที่ในตารางแฮช / พจนานุกรมและกลับมา อ้างอิงถึงที่ จากนั้นคุณสามารถเรียกการแปลงข้อความบนอินสแตนซ์เดียวกันได้ การสร้างอินสแตนซ์ใหม่สำหรับการโทรทุกครั้งและการละทิ้งการโทรซ้ำทุกครั้งจะทำให้สิ้นเปลือง
Davislor

3

ไม่กี่รุ่นที่ผ่านมา, C # swtich ได้รับการสนับสนุนอย่างเต็มที่สำหรับการจับคู่รูปแบบ เพื่อให้กรณี "ตรงกันหลายประเทศ" ทำได้ง่าย ในขณะที่ยังไม่มีความสามารถ แต่อินพุตหนึ่งสามารถจับคู่หลายกรณีด้วยการจับคู่รูปแบบ มันอาจจะทำให้การสแปมนั้นชัดเจนขึ้น

Npw สวิทช์สามารถถูกแทนที่ด้วยการสะสม คุณต้องใช้ผู้ได้รับมอบหมายและพจนานุกรม กระบวนการสามารถถูกแทนที่ด้วย

public delegate string ProcessDelegate(string text);

จากนั้นคุณสามารถสร้างพจนานุกรม:

var Processors = new Dictionary<string, ProcessDelegate>(){
  { "USA", EnglishProcessor },
  { "GBR", EnglishProcessor },
  { "DEU", GermanProcessor }
}

ฉันใช้ functionNames เพื่อมอบให้ผู้แทน แต่คุณสามารถใช้แลมบ์ดาไวยากรณ์เพื่อให้รหัสทั้งหมดที่นั่น ด้วยวิธีนี้คุณสามารถซ่อนคอลเลคชั่นนั้นได้ทั้งหมดเหมือนกับที่คุณเก็บสะสมขนาดใหญ่ และรหัสกลายเป็นการค้นหาแบบง่าย:

ProcessDelegate currentProcessor = Processors[country];
string processedString = currentProcessor(country);

นี่เป็นสองทางเลือก คุณอาจต้องการพิจารณาใช้ Enumerations แทนสายอักขระสำหรับการจับคู่ แต่นั่นเป็นรายละเอียดเล็กน้อย


2

ฉันอาจจะ (ขึ้นอยู่กับรายละเอียดของการใช้งานของคุณ) ไปกับCountryการเป็นวัตถุ "ของจริง" แทนที่จะเป็นสตริง คำหลักคือ "polymorphism"

ดังนั้นโดยทั่วไปจะมีลักษณะเช่นนี้:

public interface Country {
   string Process(string text);
}

จากนั้นคุณสามารถสร้างประเทศพิเศษสำหรับประเทศที่คุณต้องการ หมายเหตุ: คุณไม่ได้มีการสร้างCountryวัตถุสำหรับทุกประเทศคุณสามารถมีหรือแม้กระทั่งLatinlikeCountry GenericCountryคุณสามารถรวบรวมสิ่งที่ควรทำแม้กระทั่งการนำผู้อื่นกลับมาใช้ใหม่เช่น:

public class France {
   public string Process(string text) {
      return new GenericCountry().process(text)
         .replace('a', 'b');
   }
}

หรือคล้ายกัน Countryอาจเป็นจริงLanguageฉันไม่แน่ใจเกี่ยวกับกรณีการใช้งาน แต่ฉันได้รับจุด

นอกจากนี้วิธีการที่แน่นอนไม่Process()ควรจะเป็นสิ่งที่คุณต้องการทำจริง ชอบWords()หรืออะไรก็ตาม


1
ฉันเขียนอะไรที่ wordier แต่ฉันคิดว่านี่เป็นสิ่งที่ฉันชอบที่สุด หากกรณีการใช้งานจำเป็นต้องค้นหาวัตถุเหล่านี้ตามสตริงประเทศมันสามารถใช้วิธีการแก้ปัญหาของ Christopher การใช้อินเทอร์เฟซอาจเป็นคลาสที่อินสแตนซ์ตั้งค่าลักษณะเหมือนในคำตอบของ Michal เพื่อปรับให้เหมาะสมสำหรับพื้นที่มากกว่าเวลา
Davislor

1

คุณต้องการมอบหมายให้ (พยักหน้ารับความรับผิดชอบ) สิ่งที่รู้เกี่ยวกับวัฒนธรรมของตนเอง ดังนั้นใช้หรือสร้างโครงสร้างประเทศหรือ CultureInfo ดังกล่าวข้างต้นในคำตอบอื่น ๆ

แต่โดยทั่วไปและพื้นฐานปัญหาของคุณคือคุณกำลังสร้างโครงสร้างขั้นตอนเช่น 'ตัวประมวลผล' และนำไปใช้กับ OO OO เป็นเรื่องเกี่ยวกับการแสดงแนวคิดโลกแห่งความจริงจากโดเมนธุรกิจหรือปัญหาในซอฟต์แวร์ โปรเซสเซอร์ไม่ได้แปลสิ่งใดในโลกแห่งความเป็นจริงนอกเหนือจากซอฟต์แวร์ เมื่อใดก็ตามที่คุณมีคลาสเช่นโปรเซสเซอร์หรือผู้จัดการหรือผู้ปกครองระฆังปลุกควรดังขึ้น


0

ฉันสงสัยว่ามีรูปแบบที่จะช่วยกระบวนการประเภทนี้หรือไม่

ห่วงโซ่ของความรับผิดชอบเป็นสิ่งที่คุณอาจมองหา แต่ใน OOP ค่อนข้างยุ่งยาก ...

สิ่งที่เกี่ยวกับวิธีการทำงานมากขึ้นด้วย C #

using System;


namespace Kata {

  class Kata {


    static void Main() {

      var text = "     testing this thing for DEU          ";
      Console.WriteLine(Process.For("DEU")(text));

      text = "     testing this thing for USA          ";
      Console.WriteLine(Process.For("USA")(text));

      Console.ReadKey();
    }

    public static class Process {

      public static Func<string, string> For(string country) {

        Func<string, string> baseFnc = (string text) => text;

        var aggregatedFnc = ApplyToUpper(baseFnc, country);
        aggregatedFnc = ApplyTrim(aggregatedFnc, country);

        return aggregatedFnc;

      }

      private static Func<string, string> ApplyToUpper(Func<string, string> currentFnc, string country) {

        string toUpper(string text) => currentFnc(text).ToUpper();

        Func<string, string> fnc = null;

        switch (country) {
          case "USA":
          case "GBR":
          case "DEU":
            fnc = toUpper;
            break;
          default:
            fnc = currentFnc;
            break;
        }
        return fnc;
      }

      private static Func<string, string> ApplyTrim(Func<string, string> currentFnc, string country) {

        string trim(string text) => currentFnc(text).Trim();

        Func<string, string> fnc = null;

        switch (country) {
          case "DEU":
            fnc = trim;
            break;
          default:
            fnc = currentFnc;
            break;
        }
        return fnc;
      }
    }
  }
}

หมายเหตุ: ไม่จำเป็นต้องเป็นแบบคงที่ทั้งหมด หากคลาส Process ต้องการสถานะคุณสามารถใช้คลาส instanced หรือฟังก์ชั่นที่นำไปใช้บางส่วน;)

คุณสามารถสร้างกระบวนการสำหรับแต่ละประเทศเมื่อเริ่มต้นจัดเก็บแต่ละรายการในคอลเล็กชันที่มีการจัดทำดัชนีและดึงข้อมูลเมื่อจำเป็นด้วยต้นทุน O (1)


0

ฉันขอโทษที่ฉันนานมาแล้วประกาศเกียรติคุณคำว่า "วัตถุ" สำหรับหัวข้อนี้เพราะมันทำให้คนจำนวนมากมุ่งเน้นไปที่ความคิดน้อย ความคิดที่ยิ่งใหญ่คือการส่งข้อความ

~ Alan Kay, เกี่ยวกับการส่งข้อความ

ฉันก็จะดำเนินการตามขั้นตอนการCapitalise, RemovePunctuationฯลฯ เป็นกระบวนการย่อยที่สามารถ messaged ด้วยtextและcountryพารามิเตอร์และจะกลับมาเป็นข้อความการประมวลผล

ใช้พจนานุกรมเพื่อจัดกลุ่มประเทศที่เหมาะสมกับคุณลักษณะเฉพาะ (หากคุณต้องการรายการซึ่งจะทำงานได้ดีโดยมีต้นทุนการปฏิบัติงานเพียงเล็กน้อย) ตัวอย่างเช่น: และCapitalisationApplicableCountriesPunctuationRemovalApplicableCountries

/// Runs like a pipe: passing the text through several stages of subprocesses
public string Process(string country, string text)
{
    text = Capitalise(country, text);
    text = RemovePunctuation(country, text);
    // And so on and so forth...

    return text;
}

private string Capitalise(string country, string text)
{
    if ( ! CapitalisationApplicableCountries.ContainsKey(country) )
    {
        /* skip */
        return text;
    }

    /* do the capitalisation */
    return capitalisedText;
}

private string RemovePunctuation(string country, string text)
{
    if ( ! PunctuationRemovalApplicableCountries.ContainsKey(country) )
    {
        /* skip */
        return text;
    }

    /* do the punctuation removal */
    return punctuationFreeText;
}

private string Replace(string country, string text)
{
    // Implement it following the pattern demonstrated earlier.
}

0

ฉันรู้สึกว่าข้อมูลเกี่ยวกับประเทศควรเก็บไว้ในข้อมูลไม่ใช่ในรหัส ดังนั้นแทนที่จะเป็นพจนานุกรม CountryInfo class หรือ CapitalisationApplicableCountries คุณสามารถมีฐานข้อมูลพร้อมระเบียนสำหรับแต่ละประเทศและเขตข้อมูลสำหรับแต่ละขั้นตอนการประมวลผลแล้วการประมวลผลอาจดำเนินการผ่านเขตข้อมูลสำหรับประเทศและกระบวนการที่กำหนด การบำรุงรักษานั้นส่วนใหญ่อยู่ในฐานข้อมูลโดยมีรหัสใหม่เฉพาะเมื่อจำเป็นต้องมีขั้นตอนใหม่และข้อมูลที่มนุษย์สามารถอ่านได้ในฐานข้อมูล ขั้นตอนนี้ถือว่าเป็นขั้นตอนที่เป็นอิสระและไม่รบกวนซึ่งกันและกัน หากไม่เป็นเช่นนั้นสิ่งที่ซับซ้อน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.