C # - ไม่มีการฆ่าเหมือน overkill
ก่อนอื่นเลยที่รัก GiMmEtHaCoDeZ มาลองแยกย่อยงานของคุณ:
- อ่านตัวเลข
- เรียงพวกเขา
- เอาท์พุทตัวเลขเรียง
เนื่องจาก "แบ่งและพิชิต" เป็นกลยุทธ์ที่สำคัญมากเมื่อทำงานกับปัญหาซอฟต์แวร์ให้จัดการพวกเขาทีละครั้ง
1. การอ่าน
ปัญหาสำคัญอีกประการหนึ่งของซอฟต์แวร์คือความสามารถรอบตัว เนื่องจากยังไม่ได้ระบุว่าผู้ใช้จะป้อนหมายเลขได้อย่างไรซึ่งอาจเกิดขึ้นผ่านคอนโซลไฟล์ผ่านบริการบนเว็บ ฯลฯ อาจเป็นวิธีที่เราคิดไม่ถึงในตอนนี้ ดังนั้นสิ่งสำคัญคือโซลูชันของเราจะสามารถรองรับอินพุตประเภทต่างๆได้ วิธีที่ง่ายที่สุดในการบรรลุเป้าหมายนั่นคือการแยกส่วนที่สำคัญไปยังส่วนต่อประสานสมมติว่า
public interface IDoubleArrayReader
{
IEnumerable<double> GetDoubles();
DoubleArrayReaderType Type {get;}
}
DoubleArrayReaderType
การแจงนับอยู่ที่ไหน
public enum DoubleArrayReaderType
{
Console,
File,
Database,
Internet,
Cloud,
MockService
}
สิ่งสำคัญคือการทำให้ซอฟต์แวร์สามารถทดสอบได้ตั้งแต่เริ่มต้นดังนั้นการใช้อินเทอร์เฟซจะเป็นไปได้
public class MockServiceDoubleArrayReader : IDoubleArrayReader
{
IEnumerable<double> IDoubleArrayReader.GetDoubles()
{
Random r = new Random();
for(int i =0; i<=10; i++)
{
yield return r.NextDouble();
}
}
DoubleArrayReaderType IDoubleArrayReader.Type
{
get
{
return DoubleArrayReaderType.MockService;
}
}
}
ต่อไปคำถามเชิงตรรกะคือวิธีที่เรารู้ว่าจะโหลดสิ่งที่เหมาะสมIDoubleArrayReader
ลงในโค้ด นั่นเป็นเรื่องง่ายตราบใดที่เราใช้โรงงานที่เรียบง่าย:
public static class DoubleArrayInputOutputFactory
{
private static Dictionary<DoubleArrayReaderType, IDoubleArrayReader> readers;
static DoubleArrayInputOutputFactory()
{
readers = new Dictionary<DoubleArrayReaderType, IDoubleArrayReader>();
foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
{
try
{
var instance = Activator.CreateInstance(type);
if (instance is IDoubleArrayReader)
{
readers.Add((instance as IDoubleArrayReader).Type,
(instance as IDoubleArrayReader));
}
}
catch
{
continue;
}
}
}
public static IDoubleArrayReader CreateDoubleArrayReader(DoubleArrayReaderType type)
{
return readers[type];
}
}
โปรดทราบว่าเราใช้การไตร่ตรองเพื่อโหลดตัวอ่านที่ใช้งานอยู่ทั้งหมดดังนั้นส่วนขยายใด ๆ ในอนาคตจะพร้อมใช้งานโดยอัตโนมัติทันทีในเนื้อหาหลักของโค้ดที่เราเพิ่งทำ:
IDoubleArrayReader reader = DoubleArrayInputOutputFactory
.CreateDoubleArrayReader(DoubleArrayReaderType.MockService);
var doubles = reader.GetDoubles();
2. การประมวลผล (การเรียงลำดับ)
ตอนนี้เราต้องดำเนินการคือจัดเรียงตัวเลขที่เราได้รับ โปรดทราบว่าขั้นตอนนั้นไม่ขึ้นอยู่กับแต่ละระบบดังนั้นระบบย่อยการเรียงลำดับจึงไม่สำคัญว่าจะต้องป้อนหมายเลขอย่างไร นอกจากนี้พฤติกรรมการเรียงลำดับก็เป็นสิ่งที่อาจมีการเปลี่ยนแปลงเช่นเราอาจต้องป้อนอัลกอริทึมการเรียงลำดับที่มีประสิทธิภาพมากขึ้นแทน ดังนั้นโดยปกติเราจะแยกพฤติกรรมการประมวลผลที่ร้องขอในอินเทอร์เฟซ:
public interface IDoubleArrayProcessor
{
IEnumerable<double> ProcessDoubles(IEnumerable<double> input);
DoubleArrayProcessorType Type {get;}
}
public enum DoubleArrayProcessorType
{
Sorter,
Doubler,
Tripler,
Quadrupler,
Squarer
}
และพฤติกรรมการเรียงลำดับจะใช้อินเตอร์เฟส:
public class SorterDoubleArrayProcessor : IDoubleArrayProcessor
{
IEnumerable<double> IDoubleArrayProcessor.ProcessDoubles(IEnumerable<double> input)
{
var output = input.ToArray();
Array.Sort(output);
return output;
}
DoubleArrayProcessorType IDoubleArrayProcessor.Type
{
get
{
return DoubleArrayProcessorType.Sorter;
}
}
}
แน่นอนว่าเราจะต้องมีโรงงานในการโหลดและจัดการอินสแตนซ์การประมวลผล
public static class DoubleArrayProcessorFactory
{
private static Dictionary<DoubleArrayProcessorType, IDoubleArrayProcessor> processors;
static DoubleArrayProcessorFactory()
{
processors = new Dictionary<DoubleArrayProcessorType, IDoubleArrayProcessor>();
foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
{
try
{
var instance = Activator.CreateInstance(type);
if (instance is IDoubleArrayProcessor)
{
processors.Add((instance as IDoubleArrayProcessor).Type, (instance as IDoubleArrayProcessor));
}
}
catch
{
continue;
}
}
}
public static IDoubleArrayProcessor CreateDoubleArrayProcessor(DoubleArrayProcessorType type)
{
return processors[type];
}
}
3. การเขียนผลลัพธ์
ไม่มีอะไรจะพูดที่นี่เพราะนี่เป็นกระบวนการที่สะท้อนการป้อนข้อมูล อันที่จริงเราสามารถรวมการอ่านและการเขียนโรงงานไว้ในที่เดียวDoubleArrayInputOutputFactory
เช่นนี้
public interface IDoubleArrayWriter
{
void WriteDoublesArray(IEnumerable<double> doubles);
DoubleArrayWriterType Type {get;}
}
public enum DoubleArrayWriterType
{
Console,
File,
Internet,
Cloud,
MockService,
Database
}
public class ConsoleDoubleArrayWriter : IDoubleArrayWriter
{
void IDoubleArrayWriter.WriteDoublesArray(IEnumerable<double> doubles)
{
foreach(double @double in doubles)
{
Console.WriteLine(@double);
}
}
DoubleArrayWriterType IDoubleArrayWriter.Type
{
get
{
return DoubleArrayWriterType.Console;
}
}
}
public static class DoubleArrayInputOutputFactory
{
private static Dictionary<DoubleArrayReaderType, IDoubleArrayReader> readers;
private static Dictionary<DoubleArrayWriterType, IDoubleArrayWriter> writers;
static DoubleArrayInputOutputFactory()
{
readers = new Dictionary<DoubleArrayReaderType, IDoubleArrayReader>();
writers = new Dictionary<DoubleArrayWriterType, IDoubleArrayWriter>();
foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
{
try
{
var instance = Activator.CreateInstance(type);
if (instance is IDoubleArrayReader)
{
readers.Add((instance as IDoubleArrayReader).Type, (instance as IDoubleArrayReader));
}
}
catch
{
continue;
}
}
foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
{
try
{
var instance = Activator.CreateInstance(type);
if (instance is IDoubleArrayWriter)
{
writers.Add((instance as IDoubleArrayWriter).Type, (instance as IDoubleArrayWriter));
}
}
catch
{
continue;
}
}
}
public static IDoubleArrayReader CreateDoubleArrayReader(DoubleArrayReaderType type)
{
return readers[type];
}
public static IDoubleArrayWriter CreateDoubleArrayWriter(DoubleArrayWriterType type)
{
return writers[type];
}
}
วางมันทั้งหมดเข้าด้วยกัน
ในที่สุดโปรแกรมหลักของเราจะใช้ความสุดยอดทั้งหมดนี้ที่เราได้สร้างขึ้นดังนั้นรหัสจะเป็น:
var doubles = reader.GetDoubles();
doubles = processor.ProcessDoubles(doubles);
writer.WriteDoublesArray(doubles);
ที่เช่นเราสามารถกำหนดreader
, writer
และprocessor
การใช้
IDoubleArrayReader reader = DoubleArrayInputOutputFactory.CreateDoubleArrayReader(DoubleArrayReaderType.MockService);
IDoubleArrayProcessor processor = DoubleArrayProcessorFactory.CreateDoubleArrayProcessor(DoubleArrayProcessorType.Sorter);
IDoubleArrayWriter writer = DoubleArrayInputOutputFactory.CreateDoubleArrayWriter(DoubleArrayWriterType.Console);