2010-04-18 13 views
3

코드에 순환 의존성이 있으며 해결 방법을 모르겠습니다.C# :이 순환 종속성을 해결하는 방법은 무엇입니까?

나는 게임을 개발 중이다. NPC에는 사고, 감지 및 행동을 담당하는 세 가지 구성 요소가 있습니다. 이러한 구성 요소는 모델에 액세스하기 위해 NPC 컨트롤러에 액세스해야하지만 컨트롤러는 이러한 구성 요소를 필요로합니다. 따라서, 둘 다 그들의 생성자에서 인수로서 서로를 취한다.

ISenseNPC sense = new DefaultSenseNPC(controller, worldQueryEngine); 
IThinkNPC think = new DefaultThinkNPC(sense); 
IActNPC act = new DefaultActNPC(combatEngine, sense, controller); 
controller = new ControllerNPC(act, think); 

은 (위의 예는. 조금 단순화 매개 변수가 있습니다) 아무것도 할 수 없습니다 actthink없이

, controller, 그래서 나는 그들없이 초기화하는 것을 허용하지 않습니다. 반전은 기본적으로 마찬가지입니다. 어떻게해야합니까?

public class ControllerNPC { 
    // ... 
      public override void Update(long tick) 
     { 
      // ... 
      act.UpdateFromBehavior(CurrentBehavior, tick); 

      CurrentBehavior = think.TransitionState(CurrentBehavior, tick); 
     } 
    // ... 

} 

DefaultSenseNPC은 아무것도 충돌하는 것 있는지 확인 controller를 사용하여 : 세계에서 그 상태를 업데이트 할 thinkact를 사용하여

ControllerNPC

public class DefaultSenseNPC { 
     // ... 
      public bool IsCollidingWithTarget() 
      { 
       return worldQuery.IsColliding(controller, model.Target); 
      } 
     // ... 
    } 
+0

자신 만의 솔루션을 개발 했습니까? – Budda

답변

0

를 사용하여 두 단계 건설, 그에 객체가 관련 객체에 대한 null 참조로 생성 된 다음 set 메소드를 호출하여 참조를 설정합니다 영역 :

ISenseNPC sense = new DefaultSenseNPC(worldQueryEngine); 
IThinkNPC think = new DefaultThinkNPC(); 
IActNPC act = new DefaultActNPC(combatEngine); 
controller = new ControllerNPC(); 

sense.setController(controller); 
think.setSense(sense); 
act.setSense(sense); 
act.setController(controller); 
controller.setAct(act); 
controller.setThink(think); 

// And now the objects are ready to use. 
+0

어떻게 이런 일이 발생할 수 있습니까? 다른 프로그래머가 두 번째 단계가 필요하다는 사실을 잊을 수 있기 때문에 코드의 안정성이 떨어지지 않습니까? –

+0

또한, 나는'Controller.Act' 또는'Controller.Think'가 초기화시 이외에 설정되도록하지 않을 것입니다. –

+0

@Rosarch :이 프로그래머가 실수로 작성한 객체가 아무 것도하지 않으면, 실수를 찾아 낼 것입니다. 철저하게하기 위해, 당신은 물건들이 할 것을 요구할 때 관련'set' 메소드가 호출되었다고 주장 할 수 있습니다. 그리고 그것은 당신에게 그 문제가 무엇인지 정확하게 알려줄 수 있습니다. – RichieHindle

0

는 객체 사이의 통신 중 일부 이벤트를 사용할 수 있을까요 :

이 도메인 중심의 디자인 프로젝트 참조에 대해, 나는 약간의 시간 이전에이 문제에 대한 작은 블로그를 썼다? 나의 이해에서

+0

당신은 어떻게 생겼습니까? –

0

는, 1 주 것입니다 : 컨트롤러는 생각, 감지, 연기에 대해 알고 안 ...

난 당신이 '업데이트'컨트롤러에 대한 방법과 같은 것을 가지고 볼 (내 생각) 컨트롤러는 현재 '사고', '감지', '연기'에 따라 무언가를해야합니다.

그런 경우 모델 레벨에 'ThinkModel', 'ActModel', 'SenseModel'등 3 가지 구성 요소를 더 추가 할 것입니다. 그들은 대응하는 프로세스의 상태를 나타내야하고 다른 세계에 대해 아무것도 모르는 상태 여야합니다.

컨트롤러는 DoAction, ThinkingAbout, FeelingSomething과 같은 방법으로 Thinking, Acting, Sensing 등의 구성 요소에서이 정보를 받아서 내부에 저장해야합니다.

동시에 'ActionOccured', 'ThinkingOccured', 'SenseingOccured'와 같은 일련의 이벤트가 있어야합니다 (마지막은 'FeeledSomething'과 같은 문구가 될 수 있음).이러한 이벤트는 다음과 같아야합니다.

  • 상태가 변경된 경우에 발생합니다.
  • 은 해당 개체 모델을 제공합니다.
  • 은 구성 요소에서 수신해야합니다.

결과적으로 모델에 대해서만 알 수 있으며 각 모델은 모든 모델과 컨트롤러를 참조 할 수 있습니다. 구성 요소는 서로에 대해 알 필요가 없습니다. 컨트롤러는 구성 요소에 대해 알 필요가 없습니다. 그리고이 같은 방법으로 개체를 만들 수있을 것입니다 : 각 구성 요소의

IThinkModel modelThinkg = new ThinkModel(); 
IActModel modelAct = new ActModel(); 
ISenseModel modelSense = new SenseModel(); 

IController controller = new Controller(modelThinkg, modelAct, modelSense); 

ISenseNPC sense = new DefaultSenseNPC(controller); 
IThinkNPC think = new DefaultThinkNPC(sense); 
IActNPC act = new DefaultActNPC(combatEngine, sense, controller); 

생성자는 다음과 같이 할 수 있습니다 :이 도움이

class DefaultSenseNPC 
{ 
    DefaultSenseNPC(IController controller) 
    { 
     _controller = controller; 
     _contoller.ThinkingAbout += ContollerReceivedNewThinking; 
    } 

    private ContollerReceivedNewThinking(IModelThinking modelNewThink) 
    { 
     _modelNewThink = modelNewThink;// store it for further calculations. 
    } 
} 

희망.

P. 어떤면에서 제안 된 '아키텍처'는 사용자 인터페이스가있는 응용 프로그램에서 사용되는 MVP 패턴과 유사합니다.

관련 문제