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 } }