문제

나는 진흙 엔진을 쓰고 있으며 방금 게임 객체 모델을 시작했는데, 이는 확장 가능해야합니다.

내가 한 일이 지저분 해져서 주로 도움이 필요하지만 더 잘 작동하는 다른 솔루션을 생각할 수는 없습니다.

나는 전화 수업이 있습니다 MudObject, 그리고 다른 수업은 전화를 걸었습니다 Container, 컨테이너에는 여러 가지를 포함 할 수 있습니다 MudObjects, 그러나 a MudObject 그러나 그 자체 MudObjectS가 포함되어 있는지 알아야합니다.

그래서 그들은 다음과 같이 보입니다.

public abstract class MudObject
{
    Container containedBy;
}

public abstract class Container : MudObject
{
    List<MudObject> Contains;
}

(이는 예제이며 일부 예선 및 액세스 수정 자, 속성 등이 누락됩니다).

이제 이것 자체가 지저분 해 보이지만 믹스에 다른 것을 추가하겠습니다.

Item a MudObject 모든 시각적 품목 (예 : 무기)은 상속되지만, 이들 중 일부는 컨테이너 (가슴과 같은)이어야합니다. 그러나 C#의 여러 상속과 같은 것은 없으므로 인터페이스로 내려 오는 것이 가장 좋은 선택은 컨테이너를 인터페이스로 만드는 것입니다 (내가 볼 수있는 한). 그게 추가되는 것입니다 MudObject 컨테이너로 컨테이너가 업데이트됩니다. MudObject에스 .containedBy 값.

이 일을하게하는 아이디어, 아니면 물건을 너무 복잡하게 만드는 함정에 빠지고 있습니까?
그렇다면 무엇을 제안 할 수 있습니까?

도움이 되었습니까?

해결책

당신이 요구하는 것은 합리적이며 복합 디자인 패턴

다른 팁

나는 당신이 과도하게 복잡하고 있다고 생각합니다. mudobjects가 다른 mudobjects를 포함 할 수 있다면, 당신이 필요한 단일 기본 클래스는 다음을 따라야합니다.

public abstract class MudObject
{    
    MudObject containedBy; //technically Parent
    List<MudObject> Contains; //children
}

이것은 WinForms 및 ASP.NET의 작동 방식과 유사합니다. 많은 컨테이너 컨트롤은 모두 컨트롤이며 하위 제어 모음을 포함 할 수 있습니다.

당신이 원하는 것은 상당히 합리적입니다. 그것은 다른 컨트롤의 컨테이너가 될 수있는 Windows 양식 컨트롤과 다르지 않습니다.

당신이해야 할 일은 자신의 구현을 만드는 것입니다. List<MudObject>:

public class MudObjectList : List<MudObject>

무엇보다도 기능 추가를 구현하는 것 :

public void new Add(MudObject obj)
{
    obj.ContainedBy = this;
    base.Add(obj);
}

참고 :이 메소드 그림자는 재정의 대신에 이전 추가 기능을 추가합니다.

이런 식으로 추가시 포함시 포함 된 속성을 즉시 채 웁니다. 물론 당신의 뒷면은 null, 그것은 그것이 최상위 객체임을 의미합니다.

마지막으로, 나는 분리 할 필요가 없다고 생각합니다 MudObject 그리고 Container 컨테이너가되기 때문에 수업은 MudObject (FF는 C# 3.0 자동 속성을 사용합니다) :

public abstract class MudObject
{
    MudObject ContainedBy { get; set; }
    MudObjectList Contains { get; set; }
}

모든 mudobjects 용기를 만들지 않겠습니까? ... 또는 적어도 클래스 코드 측면에서 다른 개체를 포함 할 수 있습니다. 예를 들어

public abstract class MudObject
{
    MudObject containedBy;
    List<MudObject> contains;
}

그런 다음 객체 자체에 일종의 플래그를 설정하여 플레이어가 물체의 유형을 사용하여 파악하기보다는 실제로 물건을 객체 자체에 넣을 수 있는지 확인할 수 있습니다.

사실, 그것은 둘 다 항목이라는 것이 나쁜 생각입니다. 그리고 컨테이너. 이것은 ILIST에 대한 가정을 만드는 여러 바인딩 시나리오를 깨뜨립니다. 그래서 가슴의 경우, 나는 품목 재산을 가지고 싶어 할 것입니다 ~에 가슴은 컬렉션이지만 가슴을 가슴으로 보냅니다.

그러나 질문에 따라 질문에 대해 ...

나는 mudobject를 인터페이스로 만들고 싶은 유혹을받을 것입니다 ... 그런 식으로, 당신은 다음과 같은 것을 사용할 수 있습니다. 이것은 자동 육아와 함께 콘크리트 물체의 일반적인 용기를 제공합니다.

public interface IMudObject
{
    IMudObject Container { get; set; }
    /* etc */
}

public class MudContainer<T> : Collection<T>, IMudObject
    where T : IMudObject
{

    public IMudObject Container { get; set; }

    protected override void ClearItems()
    {
        foreach (T item in this)
        {
            RemoveAsContainer(item);
        }
        base.ClearItems();
    }

    protected override void InsertItem(int index, T item)
    {
        SetAsContainer(item);
        base.InsertItem(index, item);
    }

    protected override void RemoveItem(int index)
    {
        RemoveAsContainer(this[index]);
        base.RemoveItem(index);            
    }
    protected override void SetItem(int index, T item)
    {
        RemoveAsContainer(this[index]);
        SetAsContainer(item);
        base.SetItem(index, item);
    }

    void RemoveAsContainer(T item)
    {
        if (item != null && ReferenceEquals(item.Container, this))
        {
            item.Container = null;
        }
    }
    void SetAsContainer(T item)
    {
        if (item.Container != null)
        {
            throw new InvalidOperationException("Already owned!");
        }
        item.Container = this;
    }
}

상속 대답에 대한 구성이라는 아이디어를 가지고 사라진 것 같습니다.

아마도 나는 이런 일을 더 할 수있을 것입니다

public class Container<T> where T : MudObject
{
    List<T> Contains;
    MudObject containerOwner;

    public Container(MudObject owner)
    {
        containerOwner = owner;
    }
    // Other methods to handle parent association
}

public interface IMudContainer<T> where T : MudObject
{
    Container<T> Contains { get; }
}

public class MudObjectThatContainsStuff : IMudContainer
{
    public MudObjectThatContainsStuff()
    {
        Contains = new Container<MudObject>(this);
    }

    public Contains { get; }
}

Marc의 답변에 따라 후드 아래에서 양방향 부모-자식 관계를 유지하는 몇 가지 클래스를 작성하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top