Nesneye Dayalı Tasarım


23

Diyelim ki aşağıdakilere sahipsin:

     +--------+     +------+
     | Animal |     | Food |
     +-+------+     +----+-+
       ^                 ^
       |                 |
       |                 |
  +------+              +-------+
  | Deer |              | Grass |
  +------+              +-------+

Deergelen miras Animalve gelen Grassmiras Food.

Çok uzak çok iyi. Animalnesneler nesneleri yiyebilir Food.

Şimdi biraz karıştıralım. Şunun Lionhangisini devraldığını ekleyelim Animal.

     +--------+     +------+
     | Animal |     | Food |
     +-+-----++     +----+-+
       ^     ^           ^
       |     |           |
       |     |           |
  +------+ +------+     +-------+
  | Deer | | Lion |     | Grass |
  +------+ +------+     +-------+

Şimdi nedeniyle bir sorun var olması Lionhem yiyebilirsiniz Deerve Grassfakat Deerdeğildir Foodöyle Animal.

Birden fazla kalıtım kullanarak ve nesneye yönelik tasarım kullanarak, bu sorunu nasıl çözersiniz?

Bilginize: ASCII diyagramlarını oluşturmak için http://www.asciiflow.com adresini kullandım .


14
Gerçek dünyayı modellemek genellikle er ya da geç bir sorundur, çünkü her zaman garip bir şeyler oluyor (uçan balık, balık ya da kuş gibi? Ama bir penguen kuştur, uçamaz ve balık yiyebilir). @Ampt'ın söylediği gibi makul sesler, bir Hayvanın yediği şeylerden oluşan bir koleksiyonu olmalı.
Rob van der Veer

2
Bence Hayvan, Yiyeceklerden miras almalı. Bir şey bir Aslan yemeye kalkarsa, sadece bir InvalidOperationException atın.
RalphChapin

4
@RalphChapin: Her türlü şey aslan yer (akbaba, böcek vb.). Bence hayvan ve yiyecek, parçalanacak yapay ayrımlar çünkü yeterince geniş değiller (tüm hayvanlar, sonunda diğer hayvan yemidir). Eğer "LivingThing" dersini aldıysanız, yalnızca canlı olmayan şeyleri (mineraller, vb.) Yiyen bitkilerle uğraşmak zorunda kalacaksınız ve LivingThing.Eat (LivingThing) sahibi olmak için hiçbir şeyi bozmazsınız.
Satanicpuppy

2
Araştırmanızı paylaşmak herkese yardımcı olur. Bize ne denediğinizi ve neden ihtiyaçlarınızı karşılamadığını söyleyin. Bu, kendinize yardım etmek için zaman harcadığınızı, bariz cevapları tekrar etmemizi önlediğini ve hepsinden daha belirgin ve alakalı bir cevap almanıza yardımcı olduğunu gösteriyor. Ayrıca Nasıl
Sorulur

9
Bu soruya İmparatorluk Çağı III oyunu tarafından cevaplanmıştır. ageofempires.wikia.com/wiki/List_of_Animals Geyik ve Gazelle uygular IHuntable, Koyun ve İnek IHerdable(insan tarafından kontrol edilebilir) ve Lion sadece bu arayüzleri ima etmeyen IAnimal uygular. AOE3 instanceof, bir programın yeteneklerini sorgulamasını sağlayan belirli bir nesne (benzer ) tarafından desteklenen arabirim kümesinin sorgulanmasını destekler .
rwong

Yanıtlar:


38

IS A ilişkileri = Kalıtım

Aslan bir hayvandır

HAS A ilişkileri = Kompozisyon

Arabanın tekerleği var

CAN DO ilişkileri = Arayüzler

Yiyebilirim


5
+1 Bu kadar basit ve yine de 3 farklı ilişki tipinin güzel bir özeti
dreza

4
Alternatif: ICanBeEatenya daIEdible
Mike Weller

2
CAN HAZ ilişkileri = lolipatlar
Steven A. Lowe

1
Bu soruya nasıl cevap veriyor?
user253751

13

OO sadece gerçek dünyadan sonra kendisini örten bir metafordur. Ancak metaforlar sadece bugüne kadar gider.

Normalde OO'da bir şeyi modellemek için doğru bir yol yoktur. Bunu yapmanın bir doğru yolu belli bir problemin bir de belirli bir etki ve etki alanı nesneleri aynı olsa bile, sorununuzu değiştirirseniz iyi çalışması için beklememelisiniz.

Bu en Comp ortak bir yanılgıdır olduğunu düşünüyorum. Müh. öğrencilerin ilk yıllarında var. OO evrensel bir çözüm değildir, etki alanınızı oldukça iyi bir şekilde modelleyebilecek bazı problemler için iyi bir araçtır.

Tam olarak etki alanı bilgisi olmadığı için soruyu cevaplamadım. Ancak yukarıdakileri göz önünde bulundurarak gereksinimlerinize uyan bir şey tasarlayabilirsiniz.


3
+1 OO bir din değil bir araçtır.
mouviciel

Kabul ediyorum, eğer bu problem değişmeye ve evrimleşmeye devam ederse mükemmel bir çözüm olmayabilir. Şu anki haliyle, bu problem bir çözüm bulmak için etki alanı bilgisine sahip değil mi?
Michael Irey

Gerçekten gerçek bir dünyanın OP'de modellenmiş olduğunu mu düşünüyorsunuz? Bir örnek olarak bir ilişki modeli temsil edilir.
Basilevs,

@Basilevs Hayvanların gerçek hayatta nasıl davrandıklarından bahsettiği için aslında bu bir tür ima. IMO'nun programda hesaba katılması için bu davranışa neden ihtiyaç duyulması gerektiğiyle ilgilenilmesi gerekiyor. Bu, bazı olası tasarım önermek benim için iyi olurdu dedi.
DPM

10

Hayvanları alt sınıflarına daha da ayırmak istersiniz (ya da en azından ne yaptığınız için mantıklı). Temel hayvanlara ve iki çeşit yiyeceğe (bitki ve et) benzeyen şeylerle çalıştığınız göz önüne alındığında, bir hayvanı daha ayrıntılı tanımlamak ve ayrı tutmak için etobur ve otçul kullanmak mantıklıdır. İşte senin için çizdiğim şey.

             +----------------+                   +--------------------+
             |    Animal      |                   |      Food          |
             |----------------|<--+Interfaces+--->|--------------------|
             |                |                   |                    |
             +----------------+                   +--------------------+
                +           +                       +                 +
                |           |    Abstract Classes   |                 |
                |           |        |          |   |                 |
                v           v        v          v   v                 v
   +-----------------+  +----------------+     +------------+      +------------+
   |   Herbivore     |  |  Carnivore     |     |   Plant    |      |   Meat     |
   |-----------------|  |----------------|     |------------|      |------------|
   |Eat(Plant p)     |  |Eat(Meat m)     |     |            |      |            |
   |                 |  |                |     |            |      |            |
   +-----------------+  +----------------+     +------------+      +------------+
            +                    +                    +                   +
            |                    |                    |                   |
            v                    v                    v                   v
   +-----------------+  +----------------+     +------------+      +------------+
   |  Deer           |  |   Lion         |     |  Grass     |      |  DeerMeat  |
   |-----------------|  |----------------|     |------------|      |------------|
   |DeerMeat Die()      |void Kill(Deer) |     |            |      |            |
   +-----------------+  +----------------+     +------------+      +------------+
                                 ^                    ^
                                 |                    |
                                 |                    |
                              Concrete Classes -------+

Görebildiğiniz gibi, her ikisi de bir yeme yöntemini ortaya koyuyor, ancak ne yedikleri değişiyor. Aslan şimdi bir geyiği öldürebilir, geyik ölebilir ve DeerMeat'e geri dönebilir ve OP'lerin bir aslanın bir geyiği yemesine nasıl izin verileceğine dair orijinal soruyu cevaplar.

Tabii ki, bu çok hızlı bir şekilde ilginçleşiyor, çünkü bir Geyik de bir et türü olarak görülebiliyordu, ama işleri basit tutmak için, geyik altında bir geyik eti döndüren kill () adında bir metot oluşturacağım ve beton sınıfı etleri uzatma.


Deer daha sonra bir IMeat arayüzünü ortaya çıkarır mı?
Dan Pichelman

Et bir arayüz değil, soyut bir sınıf. Ben uygulamak nasıl eklenen bunun için mi
Ampt

Eat(Plant p)ve Eat(Meat m)her ikisi de LSP'yi ihlal ediyor.
Tulains Córdova

Nasıl yani @ user61852? Bilerek hayvan arayüzünde yiyin, böylece her hayvan türü kendine ait bir yiyeceğe sahip olabilir.
Ampt

1
TCWL (Çok karmaşık, sızıntı yapacak). Sorun dağılıyor ve ortaya çıkıyor ve çözümünüz statik, merkezi ve önceden tanımlanmış. TCWL.
Tulains Córdova

7

Tasarımım şöyle olurdu:

  1. Yiyecekler arayüz olarak bildirilir; bir IFood arayüzü ve ondan iki türetilmiş arayüz var: IMeat ve IVegetable
  2. Hayvanlar, IMeat'i uygular ve Sebzeler, IVegetable'ı uygular.
  3. Hayvanların iki torunu var, Etçiller ve Cibivorlar
  4. Etçiller IMeat örneğini alan Eat yöntemine sahiptir
  5. Herbivorlar, IVegetable örneğini alan Eat yöntemine sahiptir
  6. Aslan Carnivore'den iner
  7. Geyik Herbivore dan iner
  8. Çimen sebzeden iner

Hayvanlar IMeat uygular ve Deer (Herbivore) bir Hayvandır, Lion, (Carnivore) bir Hayvandır.

Geyik bir Herbivore'dur, yani IVegetable uyguladığı için Grass yiyebilir.

Etçiller IVegeable yiyemez ve Herbivorlar IMeat yiyemez.


1
Burada kalıtımın sadece kalıtsal olan türlerin hiçbir şeyi uygulamadığı zaman sınırlandırmak için miras kullanan çok sayıda numaralandırma türü görüyorum ... Kendinizi hiç bir işlevi yerine getirmeyen tipler ürettiğinizde, bu bir şeyin bir ayak izi vermesidir; Tip sistemindeki, kodun kullanılabilirliğine bir değer vermeyen bir model geliştirdiniz
Jimmy Hoffa,

Omnivorların varolduğunu hatırlayın, insanlar, maymunlar ve ayılar gibi.
Tulains Córdova

Peki hem aslanların hem de geyiklerin memeliler olduğunu nasıl eklersiniz? :-)
johannes

2
@JimmyHoffa Bunlara "marker arayüzleri" denir ve arayüzün tamamen geçerli bir kullanımıdır. Kullanımın haklı olup olmadığına karar vermek için kod gözden geçirilmesi gerekir, ancak birçok kullanım durumu vardır (bunun gibi, Grass yemeye çalışan bir Aslanın bir NoInterface istisnası atacağı gibi). İşaretleyici arayüzü (veya eksikliği), bir yöntem desteklenmeyen argümanlarla çağrılırsa atılacak bir istisnayı önceden bildirmeye hizmet eder.
rwong

1
@wwong Kavramı anlıyorum, daha önce resmileştirilmiş duymadım; Sadece deneyimlerim, üzerinde çalıştığım bir kod üssünün her zaman olduğu, onları daha karmaşık ve sürdürmesi daha zor hale getiriyor. Belki de benim deneyimim, insanların yanlış kullandığı yerde oldu.
Jimmy Hoffa,

5

Bir hayvanın yiyebileceği yiyecekler aslında bir hiyerarşi oluşturmaz, bu durumda doğa, basit nesne yönelimli modellemeye uymadıkça kabul edilemez bir şekilde başarısız olmuştur (eğer öyleyse bile, hayvanın gıda olduğu için gıdadan miras alması gerektiğine dikkat edin).

Bir hayvan ne yiyebilir gıdaların Bilgi olamaz bu yüzden sadece gıda hiyerarşisinin bazı üyesi bir başvuru sahip canlı bütünüyle sınıfların biriyle yemek ne şeyler söylemek yeterli olamaz.

Çok çok fazla ilişki var. Bu, her hayvan eklediğinizde, ne yiyebileceğini bulmanız ve ne zaman bir yemek eklediğinizde, onu ne yiyebileceğini bulmanız gerektiği anlamına gelir. Kullanılacak başka bir yapının olup olmadığı, hangi hayvanları ve gıdaları modellediğinize bağlıdır.

Çoklu kalıtım da bunu pek iyi çözmüyor. Bir hayvanın yiyebileceği şeyler ya da bir yiyeceği yiyebilecek hayvanların bir tür koleksiyonuna ihtiyacınız var.


Regex hakkında söyledikleri gibi, "Bir problemim vardı, bu yüzden regex kullandım, şimdi iki problemim var", MI, "Bir problemim vardı, bu yüzden MI kullandım, şimdi 99 problemim var" çizgisi boyunca. Neyi yiyebildiğini bildiği halde burada dürttüğünüz boşluğu izleyin, bu aslında modeli bir ton basitleştirir. Bağımlılık inversiyonu FTW.
Jimmy Hoffa,

1

Soruna farklı yönlerden yaklaşacağım: OOP davranış hakkında. Senin durumunda, Grassçocuk olmak için bazı davranışlar var Foodmı? Yani senin durumunda, Grasssınıf olmayacak , ya da en azından, miras kalmayacak Food. Ayrıca, derleme zamanında kimin yiyebileceğini zorlamanız gerekiyorsa, Animalsoyutlamaya ihtiyacınız varsa sorgulanabilir . Ayrıca, devam etmemek için olmasa da, ot yiyen etobur görmek nadir değildir.

Bu yüzden şunu tasarlardım (ASCI sanatıyla uğraşmaz):

IEdibleözelliğiyle Typeet, bitki, karkas vb .. bir enum olan, (bu genellikle değişmez ve herhangi bir spesifik davranışı yok, bu nedenle sınıf hiearchy olarak bu modellemek için gerek yoktur).

AnimalCanEat(IEdible food)ve Eat(IEdible food)mantıklı olan yöntemlerle . Daha sonra, belirli hayvanlar ne zaman belirli durumlarda verilen yiyecekleri yiyip kontrol edebileceklerini kontrol edebilir ve daha sonra devam etmek / başka bir şey yapmak için o yiyecekleri yiyebilir. Ayrıca, Carnivore, Herbivore, Omnivore sınıflarını da hayvan hiyerarşisinin bir parçası olarak Strateji kalıbı olarak modelleyeceğim .


1

TL; DR: İçeriği olan tasarım veya model.

Sorunuzun zor olduğunu düşünüyorum çünkü çözmeye çalıştığınız asıl sorunun bağlamından yoksun. Bazı modelleriniz ve bazı ilişkileriniz var, ancak çalışması gereken çerçeveden yoksundur. Bağlam olmadan, modelleme ve metaforlar iyi çalışmaz, kapıyı birden fazla yoruma açık bırakın.

Verilerin nasıl tüketileceğine odaklanmanın daha verimli olduğunu düşünüyorum. Veri kullanım modeline sahip olduğunuzda, modellerin ve ilişkilerin ne olması gerektiği ile geriye doğru çalışmak daha kolaydır.

Örneğin, daha ayrıntılı gereksinimler farklı nesne ilişkilerini gerektirecektir:

  • benzeri Animals eatolmayan şeyleri desteklemekFoodGastroliths
  • desteklemesi Chocolateolarak Poisoniçin Dogsdeğil, içinHumans

Nasıl modellenirse alıştırmaya başlarsak, Gıda Arayüzünün sunduğu basit ilişki en iyisi olabilir; ve eğer bu toplam ise sistemdeki ilişkilerin nasıl bir sonuç olduğunu sizde. Bununla birlikte, sadece birkaç ek gereklilik ya da ilişki daha basit durumda işe yarayan modelleri ve ilişkileri büyük ölçüde etkileyebilir.


Katılıyorum ama bu sadece küçük bir örnek ve dünyayı modellemeye çalışmıyordu. Örneğin, Lastik ve Plakaları yiyen bir Köpekbalığına sahip olabilirsiniz. Herhangi bir nesneyi yiyen bir yöntemle bir ebeveyni soyut bir sınıf oluşturabilirsiniz ve Food bu abstact sınıfı uzatabilir.
hagensoft

@hagensoft: Kabul etti. Bazen taşınıyorum, çünkü verilerin nasıl tüketilmesi ve kullanılması gerektiğine bakmak yerine, hemen ele geçirdikleri bir metaforu temel alan geliştiricilerin modellemelerini sürekli görüyorum. İlk fikre dayanarak bir OO tasarımına evlenirler ve sonra çözümlerini soruna uygun hale getirmek yerine, çözümlerine uymaya zorlarlar.
dietbuddha

1

ECS miras üzerinden kompozisyon yaklaşımı:

An entity is a collection of components.
Systems process entities through their components.

Lion has claws and fangs as weapons.
Lion has meat as food.
Lion has a hunger for meat.
Lion has an affinity towards other lions.

Deer has antlers and hooves as weapons.
Deer has meat as food.
Deer has a hunger for plants.

Grass has plant as food.

pseudocode:

lion = new Entity("Lion")
lion.put(new Claws)
lion.put(new Fangs)
lion.put(new Meat)
lion.put(new MeatHunger)
lion.put(new Affinity("Lion"))

deer = new Entity("Deer")
deer.put(new Antlers)
deer.put(new Hooves)
deer.put(new PlantHunger)

grass = new Entity("Grass")
grass.put(new Plant)

Naturebir systemonlar genelleştirilmiş sorgu işlevi aracılığıyla ne bileşenleri arayan bu kişiler aracılığıyla döngüler söyledi. NatureEt açlığı olan varlıkların, etleri yiyecek olarak kullandıkları diğer varlıklara silahlarını kullanarak saldırmaları; Saldırı başarılı olursa, işletme kurbanla beslenecek ve bu noktada kurban etten yoksun bırakılmış bir ceset haline gelecektir. Natureaçlığa sahip olan bitkilerin, yiyecekleri olan bitkileri besleyen varlıklara var olmaları koşuluyla beslenmelerini sağlayacaktır.

Nature({lion, deer, grass})

Nature(entities)
{
    for each entity in entities:
    {
       if entity.has("MeatHunger"):
           attack_meat(entity, entities.with("Meat", exclude = entity))
       if entity.has("PlantHunger"):
           eat_plants(entity, entites.with("Plant", exclude = entity))
    }
}

Belki Grassgüneş ışığına ve suya ihtiyaç duymak için uzatmak istiyoruz ve güneş ışığını ve suyu dünyamıza tanıtmak istiyoruz. Ancak Grassbunları doğrudan olmadığı gibi arayamazsınız mobility. AnimalsAyrıca suya ihtiyaç duyabilir, ancak aktif olduklarından beri aktif olarak arayabilirler mobility. Sadece yeni bileşenler eklediğimizden ve sistemlerimizin (veya sistem sayımızın) davranışını genişlettiğimiz için, tüm tasarımın kırılmalarını gerçekleştirmeden, bu modeli genişletmeye ve değiştirmeye devam etmek oldukça kolaydır.


0

Birden fazla kalıtım kullanarak ve nesneye yönelik tasarım kullanarak, bu sorunu nasıl çözersiniz?

Çoğu şey gibi, buna da bağlı .

Bu ne olduğuna bağlıdır sen gör 'Bu sorun' olması.

  • Bu genel bir uygulama sorunu mu , örneğin seçtiğiniz platformda çoklu kalıtım eksikliğinin nasıl giderileceği?
  • Sadece bu özel durum için bir tasarım sorunu mu var , örneğin hayvanların da gıda olduğu gerçeğini nasıl modelleyeceksiniz?
  • Alan modelinde felsefi bir problem mi var , örneğin öngörülen pratik uygulama için 'yiyecek' ve 'hayvan' geçerli, gerekli ve yeterli sınıflandırmalar mı?

Genel uygulama problemini soruyorsanız, cevap çevrenizin yeteneklerine bağlı olacaktır. IFood ve IAnimal arayüzleri, her iki arayüzü de uygulayan EdibleAnimal alt sınıfıyla birlikte çalışabilir. Ortamınız arayüzleri desteklemiyorsa, Hayvan'ı yalnızca Yiyeceklerden miras edin.

Bu özel tasarım problemini soruyorsanız, sadece Animal'ı Food'dan devralın. İşe yarayabilecek en basit şey bu.

Bu tasarım konseptleri hakkında soru soruyorsanız, cevap, modelle ne yapmak istediğinize kesinlikle bağlı. Bir köpek-yiyin-köpek video oyunu ya da hayvanat bahçesindeki yemleme programlarını izlemek için bile olsa, çalışması yeterli olabilir. Hayvan davranış kalıpları için kavramsal bir model için, muhtemelen biraz sığ.


0

Kalıtım, her zaman başka bir şey olan ve değişmeyen bir şey için kullanılmalıdır. Çim her zaman yemek değildir. Mesela ben çim yemem.

Çim bazı hayvanlar için besin maddesi rolünü oynar .


Bu sadece bir soyutlama. Bu bir gereksinimse, Bitki soyut sınıfını genişleten ve insanların, insanların yedikleri bitkileri somut sınıflar halinde gruplandıracak 'HumanEatablePlants' gibi soyut bir sınıf yemesini sağlayan daha fazla bölümler oluşturabilirsiniz.
hagensoft

0

Sadece OO'nun temel sınırlamasına rastladınız.

OO hiyerarşik yapılarla iyi çalışır. Ancak bir kez katı hiyerarşilerden uzaklaştığınızda, soyutlama o kadar da işe yaramaz.

Bu sınırlamaların üstesinden gelmek için kullanılan metamorfoz bileşimleri vb. Hakkında her şeyi biliyorum, ancak bunlar beceriksiz ve daha da önemlisi belirsiz ve kurallara uyulması zor.

İlişkisel veri tabanları öncelikle katı hiyerarşik yapıların sınırlamalarından uzaklaşmak için icat edildi.

Çimlerinizi örnek almak için bir yapı malzemesi, kağıt için bir hammadde, bir kıyafet malzemesi, bir ot veya bir ürün olabilir.

Bir geyik evcil hayvan, hayvancılık, hayvanat bahçesi hayvanı veya korunan bir tür olabilir.

Bir aslan aynı zamanda bir hayvanat bahçesi hayvanı ya da korunan bir tür olabilir.

Hayat basit değil.


0

Birden fazla kalıtım kullanarak ve nesneye yönelik tasarım kullanarak, bu sorunu nasıl çözersiniz?

Ne sorunu Bu sistem ne yapar? Siz cevaplayana kadar, hangi sınıfların gerekli olabileceği hakkında hiçbir fikrim yok. Etobur ve otobur ve bitkilerle ekoloji modellemeye mi çalışıyorsunuz, tür popülasyonlarını geleceğe yansıtıyor musunuz? Bilgisayarın 20 soruyu oynamasını mı istiyorsun?

Herhangi bir kullanım durumu tanımlanmadan önce tasarıma başlamak zaman kaybıdır. Bunu, yaklaşık on kişilik bir ekibin, fotoğrafları kullanarak yazılımı kullanarak bir Airline OO modeli üretmeye başladığında saçma uçlara götürdüğünü gördüm. İki yıl boyunca, akılda hiçbir iş problemi olmadan modelleme yaptılar. Sonunda müşteri beklemekten bıktı ve takımdan gerçek bir sorunu çözmesini istedi. Tüm bu modelleme tamamen işe yaramazdı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.