コンビネーションモード拡張、選択された再帰
17188 ワード
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:
------------------------
");
foreach (var item in corporate.Enumerate(new LeafMatchRule()))
Trace.WriteLine(item.Name );
}
#endregion
}
}