技术开发 频道

结构型模式篇-组合模式(Composite Pattern)


    如果有人用过Enterprise Library2.0,一定在源程序中看到了一个叫做ObjectBuilder的程序集,顾名思义,它是用来负责对象的创建工作的,而在ObjectBuilder中,有一个被称为定位器的东西,通过定位器,可以很容易的找到对象,它的结构采用链表结构,每一个节点是一个键值对,用来标识对象的唯一性,使得对象不会被重复创建。定位器的链表结构采用可枚举的接口类来实现,这样我们可以通过一个迭代器来遍历这个链表。同时多个定位器也被串成一个链表。具体地说就是多个定位器组成一个链表,表中的每一个节点是一个定位器,定位器本身又是一个链表,表中保存着多个由键值对组成的对象的节点。所以这是一个典型的Composite模式的例子,来看它的结构图:

                                   图6


正如我们在图中所看到的,IReadableLocator定义了最上层的定位器接口方法,它基本上具备了定位器的大部分功能。

部分代码:
public interface IReadableLocator : IEnumerable<KeyValuePair<object, object>> { //返回定位器中节点的数量 int Count { get; } //一个指向父节点的引用 IReadableLocator ParentLocator { get; } //表示定位器是否只读 bool ReadOnly { get; } //查询定位器中是否已经存在指定键值的对象 bool Contains(object key); //查询定位器中是否已经存在指定键值的对象,根据给出的搜索选项,表示是否要向上回溯继续寻找。 bool Contains(object key, SearchMode options); //使用谓词操作来查找包含给定对象的定位器 IReadableLocator FindBy(Predicate<KeyValuePair<object, object>> predicate); //根据是否回溯的选项,使用谓词操作来查找包含对象的定位器 IReadableLocator FindBy(SearchMode options, Predicate<KeyValuePair<object, object>> predicate); //从定位器中获取一个指定类型的对象 TItem Get<TItem>(); //从定位其中获取一个指定键值的对象 TItem Get<TItem>(object key); //根据选项条件,从定位其中获取一个指定类型的对象 TItem Get<TItem>(object key, SearchMode options); //给定对象键值获取对象的非泛型重载方法 object Get(object key); //给定对象键值带搜索条件的非泛型重载方法 object Get(object key, SearchMode options); }
    一个抽象基类ReadableLocator用来实现这个接口的公共方法。两个主要的方法实现代码如下:
public abstract class ReadableLocator : IReadableLocator { /**//// <summary> /// 查找定位器,最后返回一个只读定位器的实例 /// </summary> public IReadableLocator FindBy(SearchMode options, Predicate<KeyValuePair<object, object>> predicate) { if (predicate == null) throw new ArgumentNullException("predicate"); if (!Enum.IsDefined(typeof(SearchMode), options)) throw new ArgumentException(Properties.Resources.InvalidEnumerationValue, "options"); Locator results = new Locator(); IReadableLocator currentLocator = this; while (currentLocator != null) { FindInLocator(predicate, results, currentLocator); currentLocator = options == SearchMode.Local ? null : currentLocator.ParentLocator; } return new ReadOnlyLocator(results); } /**//// <summary> /// 遍历定位器 /// </summary> private void FindInLocator(Predicate<KeyValuePair<object, object>> predicate, Locator results, IReadableLocator currentLocator) { foreach (KeyValuePair<object, object> kvp in currentLocator) { if (!results.Contains(kvp.Key) && predicate(kvp)) { results.Add(kvp.Key, kvp.Value); } } } }







0
相关文章