Apa yang Membuat Iterator Pola Desain?

9

Saya telah bertanya-tanya apa yang membuat Iterator istimewa jika dibandingkan dengan konstruksi serupa lainnya, dan yang membuat Gang of Four mencantumkannya sebagai pola desain.

Iterator didasarkan pada polimorfisme (hierarki koleksi dengan antarmuka umum) dan pemisahan masalah (iterasi pada koleksi harus independen dari cara data disusun).

Tetapi bagaimana jika kita mengganti hirarki koleksi dengan, misalnya, hirarki objek matematika (integer, float, complex, matrix dll) dan iterator oleh kelas yang mewakili beberapa operasi terkait pada objek-objek ini, misalnya fungsi daya. Diagram kelas akan sama.

Kami mungkin dapat menemukan banyak contoh serupa seperti Writer, Painter, Encoder, dan mungkin yang lebih baik, yang bekerja dengan cara yang sama. Namun saya belum pernah mendengar ini disebut Pola Desain.

Jadi apa yang membuat Iterator spesial?

Apakah ini fakta yang lebih rumit karena memerlukan keadaan yang bisa berubah untuk menyimpan posisi saat ini dalam koleksi? Tapi kemudian, keadaan yang bisa berubah biasanya tidak dianggap diinginkan.


Untuk memperjelas poin saya, izinkan saya memberikan contoh yang lebih rinci.

Inilah masalah desain kami:

Katakanlah kita memiliki hierarki kelas dan operasi yang didefinisikan pada objek kelas ini. Antarmuka operasi ini sama untuk setiap kelas, tetapi implementasinya dapat sangat berbeda. Juga diasumsikan bahwa masuk akal untuk menerapkan operasi beberapa kali pada objek yang sama, katakan dengan parameter yang berbeda.

Berikut adalah solusi yang masuk akal untuk masalah desain kami (praktis generalisasi dari pola iterator):

Untuk pemisahan masalah, implementasi operasi tidak boleh ditambahkan sebagai fungsi ke hierarki kelas asli (objek operan). Karena kita ingin menerapkan operasi beberapa kali pada operan yang sama, itu harus diwakili oleh objek yang memegang referensi ke operan, bukan hanya oleh fungsi. Oleh karena itu objek operan harus menyediakan fungsi yang mengembalikan objek yang mewakili operasi. Objek ini menyediakan fungsi yang melakukan operasi aktual.

Sebuah contoh:

Ada kelas dasar atau antarmuka MathObject(nama bodoh, saya tahu, mungkin seseorang memiliki ide yang lebih baik.) Dengan kelas turunan MyIntegerdan MyMatrix. Untuk setiap MathObjectoperasi Powerharus didefinisikan yang memungkinkan perhitungan kuadrat, kubus dan sebagainya. Jadi kita bisa menulis (di Jawa):

MathObject i = new MyInteger(5);
Power powerOfFive = i.getPower();
MyInteger square = powerOfFive.calculate(2); // should return 25
MyInteger cube = powerOfFive.calculate(3); // should return 125
Frank Puffer
sumber
5
"Diagram kelas akan sama" - lalu apa? Pola desain bukan diagram kelas. Ini adalah abstraksi tingkat tinggi untuk kelas solusi untuk masalah berulang.
Doc Brown
@DocBrown: Benar, tetapi bukankah operasi matematika, menulis objek ke file, output grafis atau menyandikan masalah berulang data, seperti iterasi?
Frank Puffer
Pilihan Pola Desain bersifat subyektif (yaitu di mata "desainer", atau orang yang menilai desain). Penamaan pola desain dimaksudkan untuk menjadi agnostik-domain (sehingga kita tidak terganggu dengan pemikiran bahwa itu adalah domain-spesifik). Hanya pendapat saya, saya tidak punya referensi untuk dikutip.
rwong
@ Frankpuffer Jika Anda menguraikan solusi umum untuk menulis objek ke file, Anda dapat menuliskan solusi Anda dan menyebutnya Pola Penulisan Objek jika melakukannya sangat membantu.
Brandin
3
Anda terlalu memikirkan ini. Pola Desain adalah solusi terkenal untuk masalah komputasi yang umum, dan hanya itu yang ada. Anda menggunakan pola ketika Anda bisa mengenali dan menerapkan manfaat yang diberikannya.
Robert Harvey

Jawaban:

9

Sebagian besar pola dari buku GoF memiliki kesamaan berikut:

  • mereka memecahkan masalah desain dasar , menggunakan cara berorientasi objek
  • orang sering menghadapi masalah semacam ini dalam program sewenang-wenang, secara mandiri dari domain atau bisnis
  • mereka adalah resep untuk membuat kode lebih dapat digunakan kembali, seringkali dengan membuatnya lebih SOLID
  • mereka menghadirkan solusi kanonik untuk masalah ini

Masalah yang dipecahkan oleh pola-pola ini sangat mendasar sehingga banyak pengembang memahaminya terutama sebagai solusi untuk fitur bahasa pemrograman yang hilang , yang merupakan sudut pandang IMHO yang valid (perhatikan bahwa buku GoF berasal dari 1995, di mana Java dan C ++ tidak menawarkan begitu banyak fitur seperti hari ini).

Pola iterator cocok dengan deskripsi ini: itu memecahkan masalah dasar yang terjadi sangat sering, terlepas dari domain tertentu, dan seperti yang Anda tulis sendiri itu adalah contoh yang baik untuk "pemisahan masalah". Seperti yang sudah pasti Anda ketahui, dukungan iterator langsung adalah sesuatu yang Anda temukan dalam banyak bahasa pemrograman kontemporer saat ini.

Sekarang bandingkan ini dengan masalah yang Anda pilih:

  • menulis ke file - yaitu IMHO tidak cukup "dasar". Ini adalah masalah yang sangat spesifik. Juga tidak ada solusi kanonik yang baik - ada banyak pendekatan berbeda cara menulis ke file, dan tidak ada "praktik terbaik" yang jelas.
  • Painter, Encoder: apa pun yang ada dalam pikiran Anda dengan masalah itu, masalah-masalah itu terlihat bahkan kurang mendasar bagi saya, dan bahkan domain tidak independen.
  • memiliki fungsi "kekuatan" yang tersedia untuk berbagai jenis objek: pada pandangan pertama, itu mungkin layak dilakukan suatu pola, tetapi solusi yang Anda usulkan tidak meyakinkan saya - itu lebih terlihat seperti upaya untuk menyemir fungsi daya menjadi sesuatu yang mirip dengan pola iterator. Saya menerapkan banyak kode dengan perhitungan teknik, tetapi saya tidak dapat mengingat situasi di mana pendekatan yang mirip dengan objek fungsi daya Anda akan membantu saya (namun, iterator adalah sesuatu yang harus saya tangani setiap hari).

Selain itu, saya tidak melihat apa pun dalam contoh fungsi kekuasaan Anda yang tidak dapat diartikan sebagai penerapan pola strategi atau pola perintah, yang berarti bagian-bagian dasar sudah ada dalam buku GoF. Solusi yang lebih baik mungkin berisi kelebihan operator atau metode ekstensi, tetapi hal-hal itu tunduk pada fitur bahasa, dan itulah yang tidak dapat disediakan oleh "OO" yang digunakan oleh "Gang".

Doc Brown
sumber
The problems solved by these patterns are so basic that many developers think their main purpose is to be workarounds for missing programming language features- Ironisnya adalah bahwa pengembang perangkat lunak secara rutin menggunakan pola desain perangkat lunak yang berusia 20 tahun sementara masih percaya bahwa mereka sedang menulis kode canggih.
Robert Harvey
@RobertHarvey: Saya tidak berpikir banyak devs akan menerapkan pola iterator hari ini dalam "cara OO" yang disarankan oleh GoF. Mereka mengimplementasikannya secara khas dengan cara yang disediakan oleh bahasa atau lib standarnya (misalnya, dalam C # dengan menggunakan IEnumerabledan yield). Tetapi untuk pola GoF lainnya, apa yang Anda tulis mungkin benar.
Doc Brown
1
Relevan ke workarounds for missing programming language features: blog.plover.com/prog/johnson.html
jrw32982 mendukung Monica
8

The Gang of Four mengutip definisi pola Christopher Alexander:

Setiap pola menggambarkan masalah yang terjadi berulang-ulang di lingkungan kita, dan kemudian menjelaskan inti dari solusi untuk masalah itu [...]

Apa masalah yang dipecahkan oleh iterator?

Maksud: Memberikan cara untuk mengakses elemen objek agregat secara berurutan tanpa memaparkan representasi yang mendasarinya.

...

Penerapan: Gunakan pola Iterator

  • untuk mengakses konten objek agregat tanpa mengekspos representasi internal
  • untuk mendukung beberapa lintasan objek agregat
  • untuk menyediakan antarmuka yang seragam untuk melintasi berbagai struktur agregat (yaitu, untuk mendukung iterasi polimorfik).

Jadi orang dapat berargumen bahwa pola iterator adalah menurut domain-spesifik untuk koleksi. Dan itu tidak masalah. Pola lain seperti pola interpreter adalah domain-spesifik untuk domain-spesifik-bahasa, pola pabrik adalah domain-spesifik untuk pembuatan objek,…. Tentu saja ini adalah pemahaman yang agak konyol tentang "domain-spesifik". Selama ini adalah pasangan masalah-solusi yang berulang, kita dapat menyebutnya sebuah pola.

Dan ada baiknya pola Iterator ada. Hal-hal buruk terjadi jika Anda tidak menggunakannya. Anti-example favorit saya adalah Perl. Di sini, setiap koleksi (array atau hash) menyertakan status iterator sebagai bagian dari koleksi. Kenapa ini buruk? Kita dapat dengan mudah beralih pada hash dengan sementara – setiap loop:

while (my ($key, $value) = each %$hash) {
  say "$key => $value";
}

Tetapi bagaimana jika kita memanggil fungsi dalam loop body?

while (my ($key, $value) = each %$hash) {
  do_something_with($key, $value, $hash);
}

Fungsi ini sekarang dapat melakukan hampir semua yang diinginkan, kecuali:

  • menambah atau menghapus entri hash, karena ini akan mengubah urutan iterasi tak terduga (dalam C ++ - berbicara, ini akan membatalkan iterator).
  • iterate hash table yang sama tanpa melakukan copy, karena itu akan mengkonsumsi status iterasi yang sama. Ups.

Jika fungsi yang dipanggil harus menggunakan iterator, perilaku loop kami menjadi tidak terdefinisi. Itu masalah. Dan pola iterator memiliki solusi: letakkan semua status iterasi dalam objek terpisah yang dibuat per-iterasi.

Ya, tentu saja pola iterator terkait dengan pola lainnya. Misalnya, bagaimana iterator dipakai? Di Jawa, kami memiliki generik Iterable<T>dan Iterator<T>antarmuka. Tipe iterable yang konkrit ArrayList<T>menciptakan jenis iterator tertentu, sedangkan yang HashSet<T>mungkin menyediakan tipe iterator yang sama sekali berbeda. Itu mengingatkan saya pada pola pabrik abstrak, di mana Iterable<T>pabrik abstrak dan Iteratorproduknya.

Iterator polimorfik juga dapat diartikan sebagai contoh dari pola strategi. Misalnya pohon mungkin menawarkan berbagai jenis iterator (pre-order, in-order, post-order, ...). Secara eksternal, ini semua akan berbagi antarmuka iterator dan menghasilkan elemen dalam beberapa urutan. Kode klien hanya perlu bergantung pada antarmuka iterator, bukan pada algoritma traversal pohon tertentu.

Pola-pola tidak ada dalam isolasi, terpisah satu sama lain. Beberapa pola adalah solusi yang berbeda untuk masalah yang sama, dan beberapa pola menggambarkan solusi yang sama dalam konteks yang berbeda. Beberapa pola menyiratkan yang lain. Selain itu, ruang pola tidak ditutup ketika Anda membalik halaman terakhir buku Pola Desain (lihat juga pertanyaan Anda sebelumnya. Apakah Gang Empat secara menyeluruh mengeksplorasi "Pola Ruang"? ). Pola-pola yang dijelaskan dalam buku Pola Desain sangat fleksibel dan luas, terbuka untuk variasi yang tak terbatas, dan jelas bukan satu-satunya pola yang ada.

Konsep yang Anda daftarkan (menulis, melukis, menyandikan) bukanlah pola karena tidak menggambarkan kombinasi masalah-solusi. Tugas seperti "Saya perlu menulis data" atau "Saya harus menyandikan data" bukan masalah desain dan tidak termasuk solusi; "solusi" yang hanya terdiri dari "Saya tahu, saya akan membuat kelas Writer" tidak ada artinya. Tetapi jika kita memiliki masalah seperti "Saya tidak ingin gambar yang dibuat setengah jadi dilukis di layar", maka sebuah pola mungkin ada: "Saya tahu, saya akan menggunakan gambar buffer ganda!"

amon
sumber
Jawaban bagus, terima kasih. Masih belum sepenuhnya yakin bahwa apa yang Anda tulis dalam paragraf terakhir berlaku di sini. Saya telah mengedit pertanyaan saya untuk menjelaskan apa yang saya maksud.
Frank Puffer