复合设计模式&共同的后代方法

时间:2011-03-24 19:05:51

标签: c# linq design-patterns composite

我使用的是复合模式,如下图所示。基本上我的主要叶子(分配)有一个属性,持续时间,我想在各种复合材料中积累。

我还希望有一个分配计数,并能够将分配作为一个集合返回,我可以在演示文稿中用于数据绑定。

这个问题是关于C#的实现,特别是:

  1. 有一个有趣的post here有一个扩展来递归地执行此操作,以及一个完全避免递归的替代方法。你有一个共同的方法来按照我的方式进行分配吗?我还没有决定我写的代码是否感觉很尴尬,因为我对模式不熟悉,或者 尴尬!
  2. 您是否认为这里有任何简单的机会来缓存第一次迭代的结果,从而最大限度地减少进一步的迭代?
  3. 干杯,
    Berryl

    this class diagram

    Composite类

    中的代码
    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 个答案:

答案 0 :(得分:1)

  1. 您想要将所有节点的集合展平(IEnumerable allNodes)吗?如果是这样,在快速查看您链接的帖子后,我认为两种解决方案都可以。如果LukeH提到的考虑因素不适用于你的情况,我会坚持使用LINQ解决方案,因为它的清晰度,但这取决于你。

  2. 如果不修改结构,缓存很容易。如果添加和删除发生,它会变得非常复杂。 无论如何,你想通过缓存实现什么?后代计数缓存了吗?后人自己?在哪个级别?根级别或任何级别?

  3. 如果你有一个抽象类,那么使它的方法抽象而不是虚拟抛出异常或返回空集合会更优雅。

    PS。类图与代码不同步(即,持久性属性的放置)