组合模式扩展,有选择的递归

1.先定义个选择接口规则

 public interface IMatchRule
    {
        bool IsMatch(Component target);
    }
 public abstract class Component
    {
        /// <summary>
        /// 保存子节点
        /// </summary>
        protected IList<Component> children;

        /// <summary>
        /// Leaf和Composite的共同特征. setter方式注入名称
        /// </summary>
        public virtual string Name
        {
            get;
            set;
        }

        /// <summary>
        /// 其实只有Composite类型才需要真正实现的功能
        /// </summary>
        /// <param name="child"></param>
        public virtual void Add(Component child) { children.Add(child); }
        public virtual void Remove(Component child) { children.Remove(child); }
        public virtual Component this[int index] { get { return children[index]; } }

        /// <summary>
        /// 演示用的补充方法:实现迭代器,并且对容器对象实现隐性递归
        /// </summary>
        /// <returns></returns>
        public virtual IEnumerable<Component> Enumerate(IMatchRule rule)
        {
            if ((rule == null) || (rule.IsMatch(this)))
                yield return this;
            if ((children != null) && (children.Count > 0))
                foreach (Component child in children)
                    foreach (Component item in child.Enumerate(rule))
                        if ((rule == null) || (rule.IsMatch(item)))
                            yield return item;
        }
        public virtual IEnumerable<Component> Enumerate() { return Enumerate(null); }
    }
    public class Leaf : Component
    {
        /// <summary>
        /// 明确声明不支持此类操作
        /// </summary>
        /// <param name="child"></param>
        public override void Add(Component child) { throw new NotSupportedException(); }
        public override void Remove(Component child) { throw new NotSupportedException(); }
        public override Component this[int index] { get { throw new NotSupportedException(); } }
    }
  public class Composite : Component
    {
        public Composite() { base.children = new List<Component>(); }
    }

在工厂类中

 public class ComponentFactory
    {
        public Component Create<T>(string name) where T : Component, new()
        {
            return new T() { Name = name };
        }

        /// <summary>
        /// 连贯性方法(Fluent Method): 直接向某个节点下增加新的节点
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="parent"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public Component Create<T>(Component parent, string name)
            where T : Component, new()
        {
            if (parent == null) throw new ArgumentNullException("parent");
            if (!(parent is Composite)) throw new Exception("non-somposite type");
            Component instance = Create<T>(name);
            parent.Add(instance);
            return instance;
        }
    }

那么在实现中调用则

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using C = MarvellousWorks.PracticalPattern.Composite.Iterating;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MarvellousWorks.PracticalPattern.Composite.Tests.Iterating
{
    [TestClass]
    public class CompositeFixture
    {
        #region non-linq version

        class LeafMatchRule : C.IMatchRule
        {
            public bool IsMatch(C.Component target)
            {
                if (target == null) return false;
                return target.GetType().IsAssignableFrom(typeof(C.Leaf));
            }
        }

        C.Component corporate;

        /// <summary>
        /// 建立测试公司的组织结构
        /// </summary>
        [TestInitialize]
        public void Initialize()
        {
            var factory = new C.ComponentFactory();
            corporate = factory.Create<C.Composite>("corporate");           // 1
            factory.Create<C.Leaf>(corporate, "president");                 // 2
            factory.Create<C.Leaf>(corporate, "vice president");            // 3
            var sales = factory.Create<C.Composite>(corporate, "sales");    // 4
            var market = factory.Create<C.Composite>(corporate, "market");  // 5
            factory.Create<C.Leaf>(sales, "joe");                           // 6
            factory.Create<C.Leaf>(sales, "bob");                           // 7
            factory.Create<C.Leaf>(market, "judi");                         // 8
            var branch = factory.Create<C.Composite>(corporate, "branch");  // 9
            factory.Create<C.Leaf>(branch, "manager");                      // 10
            factory.Create<C.Leaf>(branch, "peter");                        // 11
        }

        [TestMethod]
        public void Test()
        {
            Assert.AreEqual<int>(7, corporate.Enumerate(new LeafMatchRule()).Count());
            Assert.AreEqual<int>(11, corporate.Enumerate().Count());

            //  验证通过增加遍历规则可以只显示所有leaf节点
            Trace.WriteLine("List all leaves:\n------------------------\n");
            foreach (var item in corporate.Enumerate(new LeafMatchRule()))
                Trace.WriteLine(item.Name );
        }

        #endregion

    }
}
原文地址:https://www.cnblogs.com/wangchuang/p/2995861.html