Misalkan Anda memiliki yang berikut:
+--------+ +------+
| Animal | | Food |
+-+------+ +----+-+
^ ^
| |
| |
+------+ +-------+
| Deer | | Grass |
+------+ +-------+
Deer
mewarisi dari Animal
, dan Grass
mewarisi dari Food
.
Sejauh ini baik. Animal
benda bisa memakan Food
benda.
Sekarang mari kita campur sedikit. Mari kita tambahkan Lion
yang mewarisi dari Animal
.
+--------+ +------+
| Animal | | Food |
+-+-----++ +----+-+
^ ^ ^
| | |
| | |
+------+ +------+ +-------+
| Deer | | Lion | | Grass |
+------+ +------+ +-------+
Sekarang kita punya masalah karena Lion
bisa makan keduanya Deer
dan Grass
, tetapi Deer
bukan Food
itu masalahnya Animal
.
Tanpa menggunakan pewarisan berganda, dan menggunakan desain berorientasi objek, bagaimana Anda mengatasi masalah ini?
FYI: Saya menggunakan http://www.asciiflow.com untuk membuat diagram ASCII.
object-oriented
object-oriented-design
Michael Irey
sumber
sumber
IHuntable
, Sheep and CowIHerdable
(dapat dikontrol oleh manusia), dan Lion hanya mengimplementasikan IAnimal, yang tidak menyiratkan antarmuka mana pun. AOE3 mendukung permintaan seperangkat antarmuka yang didukung oleh objek tertentu (mirip denganinstanceof
) yang memungkinkan program untuk menanyakan kemampuannya.Jawaban:
IS A relationship = Inheritance
Singa adalah binatang
HAS A hubungan = Komposisi
Mobil memiliki roda
CAN DO relationship = Antarmuka
Saya bisa makan
sumber
ICanBeEaten
atauIEdible
OO hanyalah sebuah metafora yang membentuk dirinya sendiri setelah dunia nyata. Tetapi metafora hanya berjalan sejauh ini.
Biasanya tidak ada cara yang tepat untuk memodelkan sesuatu di OO. Ada cara yang tepat untuk melakukannya untuk masalah tertentu di domain tertentu dan Anda seharusnya tidak berharap itu berfungsi dengan baik jika Anda mengubah masalah Anda, bahkan jika objek domain sama.
Saya pikir ini adalah kesalahpahaman paling umum Comp. Eng siswa di tahun-tahun pertama mereka. OO bukan solusi universal, hanya alat yang layak untuk beberapa jenis masalah yang dapat memodelkan domain Anda dengan cukup baik.
Saya tidak menjawab pertanyaan, justru karena kami kekurangan info domain. Tetapi dengan pemikiran di atas Anda mungkin dapat merancang sesuatu yang sesuai dengan kebutuhan Anda.
sumber
Anda ingin memecah hewan lebih lanjut ke dalam sub-kelas mereka (atau setidaknya sejauh masuk akal untuk apa yang Anda lakukan). Mengingat Anda bekerja dengan apa yang tampak seperti hewan biasa dan dua jenis makanan (tanaman dan daging), masuk akal untuk menggunakan karnivora dan herbivora untuk lebih mendefinisikan seekor hewan dan membuatnya terpisah. Inilah yang saya buat untuk Anda.
Seperti yang Anda lihat, mereka berdua mengekspos metode makan, tetapi apa yang mereka makan berubah. Singa sekarang dapat membunuh rusa, rusa dapat mati dan mengembalikan DeerMeat, dan pertanyaan awal OPs tentang bagaimana memungkinkan singa makan rusa tetapi tidak rumput dijawab tanpa rekayasa seluruh ekosistem.
Tentu saja, ini menjadi menarik dengan sangat cepat karena seekor Rusa dapat dianggap sebagai jenis daging juga, tetapi untuk menjaga hal-hal sederhana, saya akan membuat metode yang disebut kill () di bawah rusa, yang mengembalikan daging rusa, dan menempatkannya sebagai kelas beton memperpanjang daging.
sumber
Eat(Plant p)
danEat(Meat m)
keduanya melanggar LSP.Desain saya akan seperti ini:
Karena Hewan menerapkan IMeat dan Rusa adalah Hewan (Herbivora), Singa, yang merupakan (Karnivora) Hewan yang dapat makan IMeat juga dapat memakan Rusa.
Rusa adalah Herbivora, sehingga ia bisa makan Rumput karena mengimplementasikan IVegetable.
Karnivora tidak bisa makan IVegeable dan Herbivora tidak bisa makan.
sumber
Makanan apa yang bisa dimakan hewan tidak benar-benar membentuk hierarki, dalam hal ini alam gagal untuk menyesuaikan dengan pemodelan berorientasi objek sederhana (perhatikan bahwa meskipun demikian, hewan harus mewarisi dari makanan, karena itu adalah makanan).
Pengetahuan tentang makanan apa yang hewan bisa makan tidak bisa hidup sepenuhnya dengan salah satu kelas, sehingga hanya memiliki referensi ke beberapa anggota dari hirarki makanan tidak bisa cukup untuk memberi tahu Anda apa hal yang dapat Anda makan.
Itu hubungan banyak ke banyak. Ini berarti setiap kali Anda menambahkan hewan, Anda perlu mencari tahu apa yang bisa dimakannya, dan setiap kali Anda menambahkan makanan, Anda perlu mencari tahu apa yang bisa memakannya. Apakah ada struktur lebih lanjut untuk dieksploitasi tergantung pada hewan dan makanan apa yang Anda modelkan.
Berbagai warisan tidak benar-benar menyelesaikan masalah ini dengan baik. Anda membutuhkan semacam koleksi hal-hal yang bisa dimakan oleh hewan, atau hewan yang bisa memakan makanan.
sumber
Saya akan mendekati masalah dari sisi yang berbeda: OOP adalah tentang perilaku. Dalam kasus Anda, apakah
Grass
memiliki perilaku untuk menjadi anakFood
? Jadi dalam kasus Anda, tidak akan adaGrass
kelas, atau setidaknya, itu tidak akan diwarisi dariFood
. Juga, jika Anda perlu menegakkan siapa yang bisa makan apa pada waktu kompilasi, patut dipertanyakan apakah Anda perluAnimal
abstraksi. Juga, tidak jarang melihat karnivora makan rumput , meskipun bukan untuk makanan.Jadi saya akan merancang ini sebagai (tidak akan repot dengan seni ASCI):
IEdible
dengan propertiType
, yang merupakan enum dari daging, tanaman, bangkai, dll. (ini tidak akan sering berubah dan tidak memiliki perilaku tertentu, oleh karena itu tidak perlu memodelkan ini sebagai kelas hiearchy).Animal
dengan metodeCanEat(IEdible food)
danEat(IEdible food)
, yang logis. Kemudian, hewan tertentu dapat memeriksa kapan saja kemudian bisa makan makanan yang diberikan dalam keadaan tertentu dan kemudian makan makanan itu untuk mendapatkan rezeki / melakukan sesuatu yang lain. Juga, saya akan memodelkan kelas-kelas Karnivora, Herbivora, Omnivora sebagai pola Strategi , daripada sebagai bagian dari hierarki hewan.sumber
TL; DR: Desain atau model dengan konteks.
Saya pikir pertanyaan Anda sulit karena tidak memiliki konteks masalah aktual yang Anda coba selesaikan. Anda memiliki beberapa model dan beberapa hubungan, tetapi tidak memiliki kerangka kerja yang harus digunakan. Tanpa konteks, pemodelan dan metafora tidak berfungsi dengan baik membiarkan pintu terbuka untuk banyak interpretasi.
Saya pikir lebih produktif untuk fokus pada bagaimana data akan dikonsumsi. Setelah Anda memiliki pola penggunaan data, lebih mudah untuk bekerja mundur seperti apa model dan hubungan yang seharusnya.
Misalnya persyaratan yang lebih rinci akan memerlukan hubungan objek yang berbeda:
Animals
eat
tidakFood
sukaGastroliths
Chocolate
sebagaiPoison
untukDogs
, tetapi tidak untukHumans
Jika kita memulai latihan tentang bagaimana memodelkan hubungan sederhana yang disajikan, Food Interface mungkin yang terbaik; dan jika itu jumlah keseluruhan bagaimana hubungan dalam sistem maka Anda baik-baik saja. Namun, hanya beberapa persyaratan atau hubungan tambahan yang dapat sangat memengaruhi model dan hubungan yang berfungsi dalam kasus yang lebih sederhana.
sumber
Pendekatan komposisi-kelebihan-warisan ECS:
Kodesemu:
Nature
adalahsystem
yang loop melalui entitas ini, mencari komponen apa yang mereka miliki melalui fungsi permintaan umum.Nature
akan menyebabkan entitas dengan kelaparan daging menyerang entitas lain yang memiliki daging sebagai makanan menggunakan senjata mereka, kecuali mereka memiliki afinitas terhadap entitas itu. Jika serangan berhasil, entitas akan memakan korbannya, pada titik mana korban akan berubah menjadi mayat yang kekurangan daging.Nature
akan menyebabkan entitas yang haus akan tanaman untuk memakan entitas yang memiliki tanaman sebagai makanan, asalkan mereka ada.Mungkin kita ingin memperluas
Grass
untuk membutuhkan sinar matahari dan air, dan kami ingin memperkenalkan sinar matahari dan air ke dunia kita. NamunGrass
tidak dapat mencari ini secara langsung, karena tidak adamobility
.Animals
mungkin juga membutuhkan air, tetapi dapat secara aktif mencarinya karena mereka memiliki airmobility
. Sangat mudah untuk terus memperluas dan mengubah model ini tanpa merusak seluruh desain, karena kami hanya menambahkan komponen baru dan memperluas perilaku sistem kami (atau jumlah sistem).sumber
Seperti kebanyakan hal, itu tergantung .
Tergantung pada apa yang Anda lihat menjadi masalah ini.
Jika Anda bertanya tentang masalah implementasi umum, jawabannya akan tergantung pada kemampuan lingkungan Anda. Antarmuka IFood dan IAnimal dapat bekerja, dengan subclass EdibleAnimal yang mengimplementasikan kedua antarmuka. Jika lingkungan Anda tidak mendukung antarmuka, buat saja Hewan mewarisi dari Makanan.
Jika Anda bertanya tentang masalah desain khusus ini, cukup buat Hewan mewarisi dari Makanan. Itu hal paling sederhana yang mungkin bisa berhasil.
Jika Anda bertanya tentang konsep desain ini, jawabannya sangat tergantung pada apa yang ingin Anda lakukan dengan model tersebut. Jika itu untuk video game anjing-makan-anjing atau bahkan aplikasi untuk melacak jadwal makan di kebun binatang, mungkin cukup untuk bekerja. Jika itu untuk model konseptual untuk pola perilaku hewan, itu mungkin sedikit dangkal.
sumber
Warisan harus digunakan untuk sesuatu yang selalu merupakan hal lain, dan tidak dapat berubah. Rumput tidak selalu makanan. Misalnya, saya tidak makan rumput.
Rumput memainkan peran bahan makanan untuk hewan tertentu.
sumber
Anda baru saja menemukan batasan dasar OO.
OO bekerja dengan baik dengan struktur hierarkis. Tapi begitu Anda menjauh dari hierarki yang ketat abstraksi tidak bekerja dengan baik.
Saya tahu semua tentang komposisi metamorfosis dll. Yang digunakan untuk mengatasi keterbatasan ini tetapi mereka canggung, dan, yang lebih penting mengarah pada kode yang tidak jelas dan sulit untuk diikuti.
Basis data relasional diciptakan terutama untuk menjauh dari keterbatasan struktur hierarkis yang ketat.
Sebagai contoh, rumput juga bisa menjadi bahan bangunan, bahan baku kertas, bahan pakaian, rumput liar atau tanaman.
Rusa bisa menjadi hewan peliharaan, ternak, binatang kebun binatang, atau spesies yang dilindungi.
Singa juga bisa menjadi binatang kebun binatang atau spesies yang dilindungi.
Hidup itu tidak sederhana.
sumber
Apa masalahnya? Apa yang dilakukan sistem ini?Sampai Anda menjawab itu, saya tidak tahu kelas apa yang mungkin diperlukan. Apakah Anda mencoba membuat model ekologi, dengan karnivora dan herbivora dan tanaman, memproyeksikan populasi spesies ke masa depan? Apakah Anda mencoba agar komputer memainkan 20 pertanyaan?
Buang-buang waktu untuk memulai desain sebelum ada kasus penggunaan yang telah ditentukan. Saya telah melihat ini dibawa ke ekstrem konyol ketika tim sekitar sepuluh mulai memproduksi model OO dari sebuah Maskapai menggunakan perangkat lunak melalui gambar. Mereka bekerja selama dua tahun menjadi model tanpa memikirkan masalah bisnis yang sebenarnya. Akhirnya pelanggan bosan menunggu dan meminta tim untuk menyelesaikan masalah yang sebenarnya. Semua pemodelan itu sama sekali tidak berguna.
sumber