http://www.blogjava.net/flustar/archive/2007/12/18/composite.html
这篇文章说的很好
其实组合模式就是为了让客户端调用程序简洁,不用实现繁琐的细节,达到单一原则,后期也好扩展管理,设计模式的本质就是达到复用和维护方便
C#篇明天写上
作者给的例子有点难
public abstract class Component { protected IList<Component> children; public virtual string Name { get; set; } 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]; } } //迭代 public virtual IEnumerable<string> GetNameList() { yield return "*"+Name; if ((children != null) && (children.Count > 0)) foreach (Component child in children) foreach (string item in child.GetNameList()) yield return "--"+item; } }
public class Leaf : Component { 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 }; } //连贯方法 直接向某个节点增加新的节点 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-somsite"); Component istance = Create<T>(name); parent.Add(istance); return istance; } }
客户端调用
using System.Diagnostics; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using C = MarvellousWorks.PracticalPattern.Composite.Classic; namespace MarvellousWorks.PracticalPattern.Composite.Tests.Classic { [TestClass] public class CompositeFixture { 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>(11, corporate.GetNameList().Count()); Trace.WriteLine("List all components:\n------------------------\n"); corporate.GetNameList().ToList().ForEach(x=>Trace.WriteLine(x)); } } }
为了有效隔离客户程序与构造程序所以增加了工厂类分担了这部分工作,采用了抽象类而非接口,因为透明组合模式中,Component还需要完成一些基础的集合操作
结果如图