C # - Tidak ada pembunuhan seperti pembunuhan yang berlebihan
Pertama-tama, GiMmEtHaCoDeZ yang terhormat, mari kita coba untuk menjabarkan tugas Anda:
- Baca angkanya
- Sortir mereka
- Keluarkan angka yang diurutkan.
Karena "Membagi dan menaklukkan" adalah strategi yang sangat penting ketika bekerja dengan masalah perangkat lunak, mari kita atasi satu per satu
1. Membaca
Masalah penting lainnya dalam perangkat lunak adalah fleksibilitas. Karena tidak ditentukan bagaimana pengguna akan memasukkan angka, itu bisa terjadi melalui konsol, melalui file, melalui layanan web, dll. Mungkin bahkan beberapa metode yang tidak dapat kita pikirkan saat ini. Jadi, penting bahwa solusi kami akan dapat mengakomodasi berbagai jenis input. Cara termudah untuk mencapai itu adalah mengekstraksi bagian penting ke antarmuka, katakanlah
public interface IDoubleArrayReader
{
IEnumerable<double> GetDoubles();
DoubleArrayReaderType Type {get;}
}
di mana DoubleArrayReaderType
pencacahan diberikan dengan
public enum DoubleArrayReaderType
{
Console,
File,
Database,
Internet,
Cloud,
MockService
}
Penting juga untuk membuat perangkat lunak dapat diuji dari bawah ke atas, sehingga implementasi antarmuka akan dilakukan
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;
}
}
}
Selanjutnya, pertanyaan logisnya adalah bagaimana kita akan tahu memuat yang sesuai IDoubleArrayReader
ke dalam kode. Itu mudah asalkan kita menggunakan pabrik sederhana:
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];
}
}
Perhatikan bahwa, kami menggunakan refleksi untuk memuat semua pembaca aktif, sehingga ekstensi apa pun di masa mendatang akan tersedia secara otomatis Sekarang, di tubuh utama kode tidak aktif yang baru saja kita lakukan:
IDoubleArrayReader reader = DoubleArrayInputOutputFactory
.CreateDoubleArrayReader(DoubleArrayReaderType.MockService);
var doubles = reader.GetDoubles();
2. Memproses (menyortir)
Sekarang kita perlu memproses, yaitu mengurutkan angka yang telah kita dapatkan. Perhatikan bahwa langkah-langkahnya benar-benar independen satu sama lain, jadi untuk subsistem pengurutan, tidak masalah bagaimana angka-angka itu dimasukkan. Selain itu, perilaku penyortiran juga merupakan sesuatu yang dapat berubah, misalnya kita mungkin perlu memasukkan algoritma penyortiran yang lebih efisien. Jadi, tentu saja, kami akan mengekstrak perilaku pemrosesan yang diminta dalam antarmuka:
public interface IDoubleArrayProcessor
{
IEnumerable<double> ProcessDoubles(IEnumerable<double> input);
DoubleArrayProcessorType Type {get;}
}
public enum DoubleArrayProcessorType
{
Sorter,
Doubler,
Tripler,
Quadrupler,
Squarer
}
Dan perilaku penyortiran hanya akan mengimplementasikan antarmuka:
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;
}
}
}
Tentu saja, kita akan membutuhkan pabrik untuk memuat dan mengelola instance pemrosesan.
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. Menulis output
Tidak banyak yang bisa dikatakan di sini, karena ini adalah proses yang mencerminkan input. Bahkan, kita bisa menggabungkan pabrik baca dan tulis menjadi satu DoubleArrayInputOutputFactory
, seperti ini:
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];
}
}
Menyatukan semuanya
Akhirnya, program utama kami hanya akan menggunakan semua kehebatan yang telah kami bangun, jadi kodenya adalah:
var doubles = reader.GetDoubles();
doubles = processor.ProcessDoubles(doubles);
writer.WriteDoublesArray(doubles);
di mana, misalnya kita dapat mendefinisikan reader
, writer
dan processor
menggunakan
IDoubleArrayReader reader = DoubleArrayInputOutputFactory.CreateDoubleArrayReader(DoubleArrayReaderType.MockService);
IDoubleArrayProcessor processor = DoubleArrayProcessorFactory.CreateDoubleArrayProcessor(DoubleArrayProcessorType.Sorter);
IDoubleArrayWriter writer = DoubleArrayInputOutputFactory.CreateDoubleArrayWriter(DoubleArrayWriterType.Console);