한 가지 방법은 예를 들어 상태가 BattleUnit
를 조작하고 Troop
를 조작하는 상태에 대해 국가가, 엔티티의 특정 유형을 위해 일을 갖는 것입니다. 그런 다음 BattleUnit
당신을위한 Engaging
및 Idle
상태를 만들 것
public abstract class State<T> where T : Unit
{
protected State(T unit)
{
this.Unit = unit;
}
protected T Unit { get; private set; }
public abstract void Handle();
}
:
이
public class EngagingState : State<BattleUnit>
{
public EngagingState(BattleUnit unit)
: base(unit)
{
}
public override void Handle()
{
// Here you can implement the "engaging" logic for a BattleUnit.
this.Unit.X = ????;
this.Unit.Y = ????;
}
}
그런 다음에 동일한 기능을 수행 할 것입니다 그래서, 예를 들어, 당신은 유사한 기본 상태로 시작 것 Idle
상태 :
public class IdleState : State<BattleUnit>
{
...
}
이 두 상태
가에서 파생 인스턴스에 적용 할 수(
BattleUnit
이 추상적이지는 않습니다!).
당신이 Troop
클래스는 MarchingState
및 ChasingState
라는 두 개의 클래스를 만들 것이며, 구조가 위에 설명 된 클래스와 유사 할 것이지만, 기본 클래스는 State<Troop>
될 것입니다 들어. Handle
메서드에서는 Troop
인스턴스에 대해 "Marching"및 "Chasing"논리를 수행합니다. 나중에 당신이 차량에 대해 "쫓는"상태 싶다고 결심했다면 이제, 당신은 만들 수 있습니다 다음
public class VehicleChasingState : State<Vehicle>
{
public VehicleChasingState(Vehicle unit)
: base(unit)
{
}
public override void Handle()
{
// Here you can implement the "chasing" logic for a Vehicle.
this.Unit.X = ????;
this.Unit.Y = ????;
if(this.Unit.HasRadar)
{
// Do special "chasing" logic when the vehicle has radar.
}
}
}
이 클래스는 생성자에 Vehicle
인스턴스를 받아 들일와 Handle
방법은을 수행 할 것 차량에 대한 "쫓는"논리.여러 주체가 서로 다른 주를 보유하고있는 한 가지 이유는 주 정부의 목적이 유사하더라도 주 내에서 특수 논리를 구현할 수 있도록 허용하는 것입니다. 이 경우 Vehicle
의 "Chasing"논리는 레이더의 존재 여부를 확인하지만 Troop
의 "Chasing"상태에서는이 작업을 수행하지 않을 것입니다. :)).
편집 1 :
@zoujyjs ... 당신의 의견에 대한 답변에서이 문제를 해결하는 방법은 두 가지 정말이 있습니다 :
첫 번째는 void Handle()
방법을 포함하는 IState
인터페이스를 생성하는 것 및 베이스 State<T>
클래스에 의해 구현됩니다. Unit
클래스에는 protected IState CurrentState { get; set; }
속성이 있습니다. 파생 클래스의 각각은, 어떤 점에서,이 속성에 새로운 상태를 할당합니다 :
this.CurrentState = new EngagingState(this); // ...this is inside a BattleUnit instance
// or
this.CurrentState = new MarchingState(this); // ...this is inside a Troop instance
그런 다음 몇 가지 점에서
Unit
클래스는 단순히
this.CurrentState.Handle()
를 부를 것이다. 기본 매개 변수없이
IState
을 갖는 요점은
Unit
클래스가 상태에 의해 관리되는 인스턴스의 유형을 알 필요가 없다는 것입니다. 알아 두어야 할 것은
Handle
메서드를 호출해야한다는 것입니다.
State<T>
클래스에 제네릭 매개 변수를 추가하면 더 쉽게 논리를 구현할 수 있습니다. 아직 구체적인 유형을 받아 들일
당신은 기본 State
클래스에서 일반 매개 변수와 Unit
속성을 제거 할 수 있으며, 각각의 파생 상태 :
는하지만, 일반 매개 변수는 두 번째 옵션에 날 리드하는 필요가 없습니다 즉 BattleUnit 또는 Troop이지만 기본 클래스 인 State
에 전달하는 대신 멤버 변수로 참조를 보유합니다. 따라서 귀하의 Handle
방법은 somethig에 같이 보일 것입니다 :
public override void Handle()
{
_unit.X = ????;
_unit.Y = ????;
}
귀하의 Unit
클래스는 다음 State
에 대한 참조를 보유 할 수 있으며, 위에서 언급 한 IState
인터페이스에 대한 필요성을 무시할 수 있습니다.
State-class의 Unit에 대한 참조가 정말로 필요합니까? Unit에서 Handle-method를 호출하면 메서드에 매개 변수로 자신을 전달할 수 있습니다. Handle-method에서 올바른 유형으로 유닛을 캐스팅해야합니다. 그러나이 변경으로 인해 디자인이 조금 더 간단해질 수 있습니다. – artokai
예, 해결 방법입니다. 나는 이것이 기본적으로 이중 파견 문제라고 말하는 다른 사람에게 물었다. @YuvalItzchakov의 해결책을 수정하면 효과가 있습니다. 그것은 추상 클래스 State를 유지하면서 템플릿은 구체적인 State를 유지합니다. – zoujyjs