Bagaimana cara menyimpan beberapa tampilan data dalam memori?

8

Saya punya banyak modul. Saya dapat memecah modul-modul ini menjadi berbagai kategori yang lengkap dan tidak tumpang tindih. Misalnya, tiga kategori, dengan id yang dapat dinyatakan sebagai Animal, Vegetable, dan Mineral. Saya selanjutnya memecah kategori ini ke dalam subkategori, yang lagi berbeda, lengkap dan tidak tumpang tindih. Misalnya, id yang dapat dinyatakan sebagai Mammal, Reptile, Legume, Root, Rock, Gem. Akhirnya, di bawah kategori ini, ada modul sendiri, misalnya Cat, Dog, Iguana, Bean, Quartz, Emerald, dll

Hirarki kategori

Berikut ini adalah kasus penggunaan umum saya:

  1. Saya perlu memanggil berbagai metode pada semua modul.
  2. Saya perlu mendapatkan snapshot datar dari keadaan saat ini dari semua data di semua modul.
  3. Saya perlu memanggil berbagai metode pada semua modul dalam kategori tertentu (tetapi tidak subkategori).
  4. Saya perlu memanggil berbagai metode pada modul khusus tertentu berdasarkan ID yang diketahui.
    • Ini bisa berupa "lakukan sesuatu" atau "beri tahu saya beberapa data tentang diri Anda"
  5. Saya perlu menyimpan data agregat tentang semua modul dalam kategori tertentu (tetapi tidak subkategori).

Bagaimana saya harus menyimpan data ini?

Beberapa fakta relevan lainnya:

  • Kategori dibuat dalam runtime
    • Dengan demikian, modul tingkat bawah memang berbagi antarmuka yang sama.
  • Begitu mereka diatur, mereka tidak berubah dalam menjalankan tertentu - mereka didasarkan pada data dalam file konfigurasi.

Inilah yang saat ini saya lakukan:

  1. Saya memiliki kelas yang berisi a Map<Category, CategoryDataStructure>. Kelas ini juga mempertahankan Collection<Module> tampilan data yang terpisah untuk digunakan dengan persyaratan # 2.
  2. CategoryDataStructuretelah merantai metode delegasi yang mengirim metode panggilan ke rantai, via SubCategoryDataStructure.
  3. CategoryDataStructure juga menyimpan data agregat yang digunakan dalam persyaratan # 5.

Ini bekerja, tapi jujur ​​cukup sulit. Semuanya adalah stateful / bisa berubah dan sulit untuk diubah. Jika saya ingin menambahkan perilaku baru, saya harus menambahkannya di banyak tempat. Saat ini struktur data itu sendiri memiliki banyak logika bisnis juga; metode delegasi. Juga struktur data induk harus melakukan banyak logika bisnis untuk membuat modul tertentu dan struktur data induknya jika perlu dan struktur data induknya jika diperlukan.

Saya mencari cara entah bagaimana memecah logika manajemen data menjauh dari struktur data itu sendiri, tetapi karena bersarang itu rumit. Berikut adalah beberapa opsi lain yang telah saya pertimbangkan:

  1. Buat yang sederhana Map<Category, Map<Subcategory, Module>>, dan letakkan semua kode untuk mempertahankan statusnya di kelas yang berbeda. Perhatian saya untuk melakukan ini adalah persyaratan # 1 dan # 2, akan sulit untuk menjaga pandangan konsisten karena sekarang saya akan memiliki dua struktur data yang berbeda yang mewakili data yang sama.
  2. Lakukan segala sesuatu dalam struktur data datar, dan loop melalui seluruh struktur ketika saya sedang mencari kategori atau sub kategori tertentu.
durron597
sumber
Sudahkah Anda mempertimbangkan untuk memecah tanggung jawab "mencari tahu objek mana dalam hierarki yang akan diperiksa atau digunakan" dengan menggunakan satu atau lebih Pengunjung?
@Snowman saya belum mempertimbangkan opsi itu; apakah Anda menyarankan untuk menyimpan data flat, dan kemudian ketika saya perlu memanggil metode, kirim pengunjung ke semua orang dan periksa apakah sesuatu perlu terjadi di handleVisitorkelas?
durron597
Ini sedikit lebih rumit dari itu, saya hanya ingin memastikan sebelum saya mengetikkan seluruh jawaban.
Mungkin Anda bisa membalik struktur top-down dan melanjutkan bottom-up: thing.getType () mengembalikan "Hewan" Itu cukup datar.
noumenal

Jawaban:

6

Tampaknya masalah inti di sini adalah Anda memiliki objek yang diatur dalam hierarki berdasarkan identitas mereka, tetapi menggunakannya secara non-hierarkis.

Sebuah analogi akan menyimpan file dalam direktori berdasarkan jenis file mereka, tetapi mencari melalui setiap direktori dan hanya memuat yang tertentu berdasarkan beberapa kriteria selain dari jenisnya.


Saya mencari cara entah bagaimana memecah logika manajemen data menjauh dari struktur data itu sendiri, tetapi karena bersarang itu rumit. Berikut adalah beberapa opsi lain yang telah saya pertimbangkan:

Ini adalah tujuan yang baik, dan ada cara mudah untuk mulai membagi tanggung jawab tanpa refactor utama: gunakan Pengunjung .

Idenya adalah bahwa jika Anda perlu memeriksa atau beroperasi hanya pada elemen tertentu dalam hierarki, Anda menempatkan logika itu di pengunjung itu sendiri. Anda kemudian dapat menulis beberapa pengunjung, masing-masing beroperasi pada elemen yang berbeda, dan melakukan tindakan yang berbeda.

Setiap unit logika sekarang mandiri bagi pengunjung tertentu . Ini meningkatkan SRP-ness kode Anda. Jika Anda perlu mengubah cara operasi dilakukan, Anda hanya melakukannya pada pengunjung yang mengimplementasikan logika itu. Hirarki objek Anda harus tetap sama, minus perubahan yang dangkal untuk mengekspos data yang diperlukan.

Ada beberapa cara untuk menerapkan pengunjung tergantung pada tujuan spesifik, tetapi ide umumnya adalah setiap node dalam hierarki menerima objek pengunjung. Implementasinya terlihat seperti ini, dan dapat dimasukkan ke dalam beberapa kelas induk abstrak:

public class Node {
  public void accept(Visitor v) {
    v.accept(this);
    for (Node child : children) {
      child.accept(v);
    }
  }
}

Ini memastikan bahwa tidak peduli bagaimana Anda memasang node Anda pada saat runtime, setiap node akan diproses.

Pengunjung Anda terlihat seperti ini:

public interface Visitor {
  accept(Node n);
}

Metode pengunjung accept(Node)adalah tempat pekerjaan nyata dilakukan. Anda perlu memeriksa node dan melakukan berbagai hal secara kondisional (termasuk mengabaikan node).


Misalnya, Anda mungkin dapat melakukan hal berikut:

Node root = ...;

// Print information on the hierarchy.
root.accept(new DebugVisitor());

// Does stuff with modules, ignores subcategories.
root.accept(new FrobnicateModulesVisitor());

// Eats vegetables, ignores animals and minerals.
root.accept(new EatYourVegetableVisitor());

Setiap pengunjung adalah kelas mandiri yang berisi logika untuk setiap operasi tanpa perlu mencampur keprihatinan dengan pengunjung lain atau node.


sumber
pertanyaan singkat mengenai kelas Note Anda: di mana "anak-anak" didefinisikan ... atau apakah ini murni contoh ilustratif?
@ Tidak ada yang didefinisikan, itu murni ilustratif. Saya menganggap pembaca akan terbiasa dengan teori grafik dan pohon.
1

Tingkat sarang yang dalam menunjukkan bahwa Anda harus mengubah tindakan menjadi fungsi yang lebih kecil, yang dapat dirantai menggunakan pernyataan pengembalian. Jika Anda perlu menerapkan metode yang sama untuk beberapa input, Anda bisa memanfaatkannya function.apply()di Java 8.

Dengan asumsi bahwa item yang berbeda tidak membagikan properti apa pun, Anda dapat mengimplementasikan antarmuka , yang mengharuskan serangkaian metode tertentu diimplementasikan. Untuk setiap tingkat saya akan membuat satu antarmuka, yang kemudian diperpanjang untuk setiap sub-node, misalnya: Entity, Phylum, Species. Selain itu, Anda memerlukan tiga kelas untuk masing-masing dari tiga entitas.

Data dapat disimpan sebagai properti dari instance objek. Untuk mencapai snapshot datar saya akan mengulangi menggunakan data function.apply().

noumenal
sumber
Hai, terima kasih atas jawaban Anda. Elemen - elemen tingkat bawah berbagi antarmuka yang sama, saya pikir itu akan menjadi jelas ketika saya mengatakan mereka semua dihasilkan dalam runtime, tetapi saya telah mengedit untuk menambahkan kalimat untuk memperjelas titik itu.
durron597
Menurut saya Anda memerlukan antarmuka juga untuk tingkat selanjutnya, tetapi saya bisa saja salah.
noumenal