Составной шаблон проектирования и общие методы потомков - PullRequest
0 голосов
/ 24 марта 2011

Я использую составной шаблон, как показано на диаграмме классов ниже. В основном мой основной лист (Распределение) имеет единственное свойство, Длительность, которое я хочу накапливать в различных композитах.

Я также хочу иметь количество распределений и возможность возвращать распределения в виде коллекции, которую я могу использовать для привязки данных в презентациях.

Этот вопрос касается реализации C #, а именно:

  1. Здесь есть интересный пост , в котором есть расширение для рекурсивного выполнения, а также альтернативный подход, который полностью исключает рекурсию. Не могли бы вы найти общий способ распределения ресурсов, как я? Я еще не решил, если код, который я написал, чувствует себя неловко, потому что мне не нравится шаблон, или он является неловким!
  2. Видите ли вы здесь легкие возможности для кэширования результатов первой итерации и тем самым минимизировать дальнейшую итерацию?

Приветствия
Berryl

this class diagram

код в композитном классе

public class AllocationComposite : AllocationNode
{
    protected readonly IList<AllocationNode> _children;
    public AllocationComposite() { _children = new List<AllocationNode>(); }

    #region Implementation of AllocationNode

    public override void Adopt(AllocationNode node) ...
    public override void Adopt(IEnumerable<AllocationNode> nodes)...
    public override void Orphan(AllocationNode node)...
    public override void Orphan(IEnumerable<AllocationNode> nodes)...

    public override IEnumerable<AllocationNode> Descendants
    {
        get
        {
            return _children.Concat(_children.SelectMany(child => child.Descendants));
        }
    }

    public override IEnumerable<Allocation> Allocations
    {
        get
        {
            return Descendants.OfType<Allocation>();
        }
    }

    public override TimeSpan Duration {
        get {
            return Allocations.Aggregate(TimeSpan.Zero, (current, child) => current + child.Duration);
         }
    }

    public override int Count { get { return Allocations.Count(); } }

    #endregion

    public override string ToString() {
        return String.Format("{0} for {1}", 
            "allocation".PluralizeWithCount(Count), 
            "hour".PluralizeWithCount(Duration.TotalHours, "F2"));
    }
}

}

Реализация по умолчанию в абстрактном компоненте

public abstract class AllocationNode: Entity, IAllocationNode
{
    #region Implementation of AllocationNode

    public virtual TimeSpan Duration { get { return TimeSpan.Zero; } set {  } }

    public virtual void Adopt(AllocationNode node) { throw new InvalidOperationException(...)); }
    public virtual void Adopt(IEnumerable<AllocationNode> nodes) { throw new InvalidOperationException(...)); }
    public virtual void Orphan(AllocationNode node) { throw new InvalidOperationException(...)); }
    public virtual void Orphan(IEnumerable<AllocationNode> nodes) { throw new InvalidOperationException(...)); }

    public virtual int Count { get { return 1; } }

    public virtual IEnumerable<AllocationNode> Descendants { get { return Enumerable.Empty<AllocationNode>(); } }

    public virtual IEnumerable<Allocation> Allocations { get { return Enumerable.Empty<Allocation>(); } }

    #endregion
}

1 Ответ

1 голос
/ 25 марта 2011
  1. Вы хотите, чтобы коллекция всех узлов была сведена (IEnumerable allNodes)? Если так, то после быстрого просмотра поста, на который вы ссылаетесь, я думаю, что оба решения в порядке. Если упоминания LukeH не относятся к вашему делу, я бы остановился на решении LINQ из-за его ясности, но оно зависит от вас.

  2. Кэширование легко, если вы не изменяете свою структуру. Это становится очень сложным, если происходит добавление и удаление. В любом случае, чего вы хотите достичь с помощью кэширования? Кэшированные потомки подсчитали? Сами потомки? На каком уровне? Корневой уровень или любой другой уровень?

Если у вас есть абстрактный класс, было бы более элегантно сделать его методы абстрактными, а не виртуальными исключениями или возвращением пустых коллекций.

PS. Диаграмма классов не синхронизирована с кодом (т.е. размещение свойства Duration)

...