객체 지향 디자인 Animal및 Grass상속합니다 Food. 여태까지는 그런대로 잘됐다. Animal물건을 먹을

다음이 있다고 가정하십시오.

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

Deer에서 상속 AnimalGrass상속합니다 Food.

여태까지는 그런대로 잘됐다. Animal물건을 먹을 수 Food있습니다.

이제 조금 섞어 봅시다. Lion에서 상속되는 a 를 추가 할 수 있습니다 Animal.

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

이제 우리는 때문에 문제가이 Lion모두를 먹을 수 Deer하고 Grass있지만, Deer되지 Food그 것이다 Animal.

다중 상속을 사용하지 않고 객체 지향 디자인을 사용하여이 문제를 어떻게 해결합니까?

참고 : http://www.asciiflow.com 을 사용하여 ASCII 다이어그램을 만들었습니다.



답변

IS 관계 = 상속

사자는 동물입니다

A 관계 = 구성

차에 바퀴가있다

CAN DO 관계 = 인터페이스

ICanEat


답변

OO는 실제 세계를 뒤덮는 은유 일뿐입니다. 그러나 은유는 지금까지만 진행되었습니다.

일반적으로 OO에서 무언가를 모델링하는 올바른 방법은 없습니다. 특정 도메인 의 특정 문제대해 올바른 방법이 있으며 도메인 개체가 동일하더라도 문제를 변경하더라도 문제가 해결 될 것으로 기 대해서는 안됩니다.

나는 이것이 대부분의 Comp에 대한 일반적인 오해라고 생각합니다. 영어 학생들은 첫 해에 있습니다. OO는 보편적 인 솔루션이 아니며, 도메인을 합리적으로 잘 모델링 할 수있는 일종의 문제에 대한 적절한 도구 일뿐입니다.

도메인 정보가 없기 때문에 질문에 대답하지 않았습니다. 그러나 위의 사항을 염두에두고 필요에 맞는 것을 설계 할 수 있습니다.


답변

동물을 하위 클래스로 더 세분화하고 싶거나 (적어도 내가하는 일에 합당한 한) 기본 동물과 두 가지 유형의 음식 (식물 및 육류)으로 작업하는 경우 육식 동물과 초식 동물을 사용하여 동물을 더 정의하고 분리 할 수 ​​있습니다. 여기 내가 당신을 위해 만든 것입니다.

             +----------------+                   +--------------------+
             |    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 -------+

보시다시피, 그들은 모두 먹는 방법을 노출하지만 먹는 음식은 변화합니다. 사자는 이제 사슴을 죽일 수 있고, 사슴은 죽고 사슴 고기를 반환 할 수 있으며, 사자가 사슴을 먹을 수는 있지만 풀은 허용하지 않는 방법에 대한 원래의 질문은 전체 생태계를 설계하지 않고도 대답 할 수 있습니다.

물론 사슴은 고기의 한 유형으로 간주 될 수 있기 때문에 매우 흥미 롭습니다. 그러나 간단하게 유지하려면 사슴 아래에 kill ()이라는 메소드를 작성하여 사슴 고기를 반환하고 그것을 콘크리트 클래스 확장 고기.


답변

내 디자인은 다음과 같습니다.

  1. 음식은 인터페이스로 선언됩니다. IMFood와 IVegetable에는 IFood 인터페이스와 두 가지 파생 인터페이스가 있습니다.
  2. 동물은 IMeat를 구현하고 야채는 IVegetable을 구현
  3. 동물은 육식 동물과 육식 동물의 두 자손이 있습니다.
  4. 육식 동물은 IMeat의 인스턴스를받는 Eat 메소드를 가지고 있습니다
  5. 초식 동물에는 IVegetable의 인스턴스를받는 Eat 메소드가 있습니다.
  6. 사자는 육식 동물에서 내려
  7. 초식 동물의 사슴
  8. 잔디는 야채에서 내려

동물은 IMeat를 구현하고 사슴은 (허비 보어) 동물이기 때문에 IMeat를 먹을 수있는 (동물) 동물 인 Lion도 사슴을 먹을 수 있습니다.

사슴은 초식 동물이므로 IVegetable을 구현하기 때문에 Grass를 먹을 수 있습니다.

육식 동물은 IVegeable을 먹을 수 없으며 초식 동물은 IMeat를 먹을 수 없습니다.


답변

동물이 먹을 수있는 음식은 실제로 계층 구조를 형성하지 않습니다.이 경우 자연은 간단한 객체 지향 모델링을 준수 할 수 없었습니다.

동물이 먹을 있는 음식에 대한 지식은 어느 수업과도 함께 살 수 없으므로 음식 계층 구조의 일부 구성원을 참조하는 것만으로는 먹을 수있는 음식을 말하기에 충분하지 않습니다.

다 대 다 관계입니다. 즉, 동물을 추가 할 때마다 먹을 수있는 음식을 찾아야하고 음식을 추가 할 때마다 먹을 수있는 음식을 찾아야합니다. 활용할 구조가 더 있는지 여부는 모델링하는 동물과 음식에 따라 다릅니다.

다중 상속은 실제로 이것을 잘 해결하지 못합니다. 동물이 먹을 수있는 음식이나 음식을 먹을 수있는 동물이 필요합니다.


답변

나는 다른 측면에서 문제에 접근 할 것이다 : OOP는 행동에 관한 것이다. 귀하의 경우, Grass자녀의 행동이 Food있습니까? 따라서 귀하의 경우에는 Grass수업이 없거나 적어도 상속되지 않습니다 Food. 또한 컴파일 타임에 먹을 수있는 사람을 강제 해야하는 경우 Animal추상화 가 필요한지 의심 스럽습니다. 또한 육식 동물풀을 먹는 육식 동물 을 볼 수 있지만 드물지 않습니다.

그래서 나는 이것을 ASCI 예술에 귀찮게하지 않을 것입니다 :

IEdibleType고기, 식물, 시체 등의 열거 형인 property 가있는 경우 (자주 변경되지 않으며 특정 동작이 없으므로 클래스 계층 구조로 모델링 할 필요가 없습니다).

Animal논리적 인 메소드 CanEat(IEdible food)Eat(IEdible food). 그런 다음 특정 동물은 주어진 상황에서 주어진 음식을 먹을 수있을 때마다 확인하고 그 음식을 먹어 생계를 유지하고 다른 것을 할 수 있습니다. 또한 동물 계층 구조의 일부보다 육식 동물, 초식 동물, 잡식 동물을 전략 패턴 으로 모델링 합니다.


답변

TL; DR : 상황에 맞는 디자인 또는 모델.

귀하의 질문은 해결하려는 실제 문제의 맥락이 없기 때문에 어렵다고 생각합니다. 일부 모델과 관계가 있지만 작동해야하는 프레임 워크가 부족합니다. 문맥이 없으면 모델링과 은유가 제대로 작동하지 않아 여러 해석에 문이 열려 있습니다.

데이터 소비 방식에 집중하는 것이 더 생산적이라고 생각합니다. 데이터 사용 패턴이 있으면 모델 및 관계가 무엇인지 역으로 쉽게 작업 할 수 있습니다.

예를 들어보다 자세한 요구 사항은 다른 객체 관계를 필요로합니다.

  • 닮지 Animals eat않은 지원FoodGastroliths
  • 지원 Chocolate으로 Poison대한 Dogs,하지만하지 않는Humans

제시된 간단한 관계를 모델링하는 방법에 대한 연습을 시작하면 Food Interface가 가장 좋습니다. 그리고 그것이 총계라면 시스템의 관계가 당신의 벌금입니다. 그러나 몇 가지 추가 요구 사항 또는 관계 만 있으면 더 간단한 경우에 작동 한 모델 및 관계에 크게 영향을 줄 수 있습니다.