2016-06-02 3 views
1

저는이 상속을 통해 합성에 대해이 wiki article을 읽었으며 예제에서는 추상 클래스를 사용했습니다. 추상적 클래스를 완전히 사용하지 않고 구체적인 클래스 만 사용하는 것을 원하지 않는다고 가정 해 보겠습니다. 나는 나의 예가 구성의 적절한 사용인지 알고 싶다. 다음 IGameobject 인터페이스가 있다고 가정 해 보겠습니다. Composition Over 상속 - 추상 클래스 피하기

public interface IGameObject 
    { 
     string Name {get;} 
    } 

와 follwing을 무기 인터페이스 :

//Note the IGameObject getter 
    public interface IWeapon 
    { 
     int Damage {get; } 
     IGameObject gameObject {get;} 
    } 

일반적으로, 내 게임, 무기 는-A을 IGameObject. 그러나 우리가 위키 기사에 따르면, 그것은 -의 관계에 따라 작곡을 사용하고 있다고 생각합니다. 칼 개체를 만들 때

이제

, 나는이 작업을 수행 할 수 있습니다 :

public class Sword : IWeapon 
{ 
     private IWeapon weaponObject; 

     public Sword(IWeapon weapon) 
     { 
      this.weaponObject = weapon; 
     } 

     public int Damage 
     { 
      get 
      { 
       return this.weaponObject.Damage; 
      } 
     } 

     public IGameObject gameObject 
     { 
      get 
      { 
       return this.weaponObject.gameObject; 
      } 
    } 

} 지금 모음 내 칼을 저장할 수

을 예를 들어, 목록 :

List<IWeapon> weapons = new List<IWeapon>(); 
weapons.add(swordObj) 

이고 여전히 내 IGameObject에 액세스 할 수 있습니다.

지금, 나는 3 개 질문 :

  1. 내가 제대로 구성을 구현 있나요?
  2. 내 소드 클래스도 IGameObject 인터페이스를 구현해야합니까?
  3. IWeapon에 IGameObject getter이 포함되어 있어도 괜찮습니까? (나는 어떤을 IGameObject 게터와 더불어, IWeapon로 저장하는 경우 그 이유는, 어떻게 그때는 IGameObject의 세부 사항을 얻을 것입니까?) 상속 대
+1

이것은 매우 이상하게 보입니다.'Sword' 클래스는'IWeapon'을 감싸는 래퍼 일뿐입니다. – Lee

+0

행동을 피하는 이유가 있습니까? 인터페이스에 메소드를 추가하고 대신 속성을 고수하고 있습니까? –

+3

이것은 has-a가 아닙니다. 동일한 객체가 여러 측면을 갖고 있기 때문에 is-a입니다. 이것은 구성하기 쉽지 않습니다. 구성은 상속보다 낫지 않습니다. 그것은 다른 것들을위한 것입니다. – usr

답변

5

구성하지만, 이해하는 매우 중요한 원칙이다, 어떤 원칙과 마찬가지로 적절하게 적용될 경우에만 긍정적 인 효과가 있습니다.

C 대 개발자는 OOP를 사용하여 '마을에 갔다'고 생각했습니다. 특히 다중 상속이 허용되는 C++와 같은 언어가 그렇습니다. 당신이 상상할 수있는 것처럼, 모든 것이 꽤 빨리 내리막 길을갔습니다.

다음과 같은 방식으로이 원칙을 쉽게 생각할 수 있습니다. OOD 중심의 개발자는 모방하려는 도메인과 가장 유사한 방식으로 실제 관계를 모델링하기를 원하므로이 관계를 면밀하고 신중하게

상속을받을 때마다 상속이 해당 엔터티 간의 실제 관계를 자세히 설명하는지 여부를 고려하십시오.

경우에 따라 무기가 실제로 게임 개체이므로 상속은 실제로 좋은 아이디어이며 그 길을 따라 다형성을 촉진합니다. 여기

는 C 내가 도메인에 적용 할 수있다 대 방법의 예입니다 :

당신이 장식 디자인 패턴이라고 여기에 사용 된 어떤
interface IGameCharacter 
{ 
    ICollection<IWeapon> Weapons {get;} 
    ICollection<IGameCharacter> Party {get;} 
} 
+2

+1 "C vs 나는 생각했습니다. 개발자들이 OOP를 통해 마을에 갔기 때문에. OOP이 확산 된 오늘과 기능 프로그래밍이 주류가되는 오늘 사이에 역사적인 유사점이 있습니다. 옛날 OOP 지도자는 약속을하고 OOP의 오히려 간단한 기계공을 과학적 신화로 흐리게 만들었습니다. 얼마 후, 사람들은 작업 OOP 시스템을 생산하는 방법을 모색하고 모범 사례를 개발했습니다. 그러나 오늘날까지도 성공한 기능은 다음과 같습니다. 유스 케이스 및 하위 시스템의 표면 영역부터 시작한 다음 적절하게 구현합니다. 잘 정의 된 서브 시스템은 시스템을 정상적으로 유지합니다. – BitTickler

+0

@BitTickler. 에 딱 맞다. –

+0

@EyalPerry - 단 하나의 질문입니다. IWeapon에 IGameObject 게터가 있으면 괜찮습니까? 그래서 IWeapon을 구현할 때 IGameObject를 반환해야합니까? –

0

.일부 수퍼 클래스 (IWeapon)를 확장하는 새 클래스를 만듭니다. 이 클래스는 데코레이터 (소드)라고합니다. 클래스에는 수퍼 클래스와 동일한 유형의 객체가 포함되어 있습니다.이 객체는 decoratee (weaponObject)라고합니다. 데코레이터의 책임 중 일부는 데코레이터에게 이전됩니다. 실제로 이것은 데코레이터가 알고리즘 중 하나에서 decoratee의 메소드 중 적어도 하나를 호출한다는 것을 의미합니다 (데 케이 테이트가 Damage 및 gameObject 모두에 사용됨).

이 점은 decorator에 이미있는 데코레이터에서 일부 동작을 다시 구현하는 것을 피하기위한 것입니다. 데코레이터가 이미 필요한 동작을 가지고 있고 데코레이터에서이 동작을 원한다면 데코레이터 패턴이 좋은 선택입니다.

다른 옵션은 데코레이터를 서브 클래 싱하고 원하는 동작을 상속 받지만 서브 클래 싱 (밀접한 결합, 원하는 동작 외에 일부 원하지 않는 동작을 상속 함, 노출되지 않아야하는 데코 레이팅에서 물건을 노출 함)과 관련된 다른 문제를 유발합니다. 데코레이터 등). 컴포지션의 이점을 원한다면 하위 클래스 화하는 대신 데코레이터 패턴 (또는 비슷한 패턴)을 구현해야합니다. 그러나 Decorator의 구체적인 유형은 런타임에 변경 될 수 있으며 장식 자 클래스에서 어떤 동작을 얻을지 결정하는 것은이 유형입니다. 이는 런타임에 동작을 변경하는 것을 지원하는 데 매우 유용 할 수 있지만 패턴을 구현할 때 알아야 할 사항이기도합니다.

이 상황에서 데코레이터 패턴이 올바른지 여부는 다음과 같은 질문을 제안합니다. 소드 클래스 (데코레이터)가 IWEAPON의 다른 하위 클래스의 일부 동작을 활용하기를 원하십니까? 귀하의 decoratee) 그리고 런타임에이 동작을 변경할 수 있기를 원하십니까? 그 질문에 예라고 대답 할 수 있다면 데코레이터 패턴은 잘 맞습니다.

관련 문제