• 设计模式之美:Iterator(迭代器)


    索引

    意图

    提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。

    Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

    结构

    参与者

    Iterator

    • 迭代器定义访问和遍历元素的接口。

    ConcreteIterator

    • 具体迭代器实现迭代器接口。
    • 对该聚合遍历时跟踪当前位置。

    Aggregate

    • 聚合定义创建相应迭代器对象的接口。

    ConcreteAggregate

    • 具体聚合实现创建相应迭代器的接口,该操作返回 ConreteIterator 的实例。

    适用性

    在以下情况下可以使用 Iterator 模式:

    • 访问一个聚合对象的内容而无需暴露它的内部表示。
    • 支持对聚合对象的多种遍历。
    • 为遍历不同的聚合结构提供一个统一的接口。

    效果

    • 它支持以不同的方式遍历一个聚合。
    • 迭代器简化了聚合的接口。
    • 在同一个聚合上可以有多个遍历。

    相关模式

    • Iterator 常被应用到 Composite 这样的递归结构上。
    • 可以使用 Factory Method 模式来实例化多态迭代器。
    • Iterator 可以使用 Memento 来捕获一个迭代的状态,在内部存储 Memento。

    实现

    实现方式(一):Iterator 模式结构样式代码。

      1 namespace IteratorPattern.Implementation1
      2 {
      3   public abstract class Iterator
      4   {
      5     public abstract object First();
      6     public abstract object MoveNext();
      7     public abstract object Current();
      8     public abstract bool IsDone();
      9     public abstract void Reset();
     10   }
     11 
     12   public abstract class Aggregate
     13   {
     14     public abstract Iterator CreateIterator();
     15   }
     16 
     17   public class ConcreteAggregate : Aggregate
     18   {
     19     private readonly ArrayList _items = new ArrayList();
     20 
     21     public int Count
     22     {
     23       get { return _items.Count; }
     24     }
     25 
     26     public object this[int index]
     27     {
     28       get { return _items[index]; }
     29       set { _items.Insert(index, value); }
     30     }
     31 
     32     public override Iterator CreateIterator()
     33     {
     34       return new ConcreteIterator(this);
     35     }
     36   }
     37 
     38   public class ConcreteIterator : Iterator
     39   {
     40     private readonly ConcreteAggregate _aggregate;
     41     private int _currentIndex = 0;
     42 
     43     public ConcreteIterator(ConcreteAggregate aggregate)
     44     {
     45       _aggregate = aggregate;
     46     }
     47 
     48     public override object First()
     49     {
     50       if (_aggregate.Count > 0)
     51         return _aggregate[0];
     52       else
     53         return null;
     54     }
     55 
     56     public override object MoveNext()
     57     {
     58       object item = null;
     59       if (_currentIndex < _aggregate.Count - 1)
     60       {
     61         item = _aggregate[++_currentIndex];
     62       }
     63 
     64       return item;
     65     }
     66 
     67     public override object Current()
     68     {
     69       return _aggregate[_currentIndex];
     70     }
     71 
     72     public override bool IsDone()
     73     {
     74       return _currentIndex >= _aggregate.Count;
     75     }
     76 
     77     public override void Reset()
     78     {
     79       _currentIndex = 0;
     80     }
     81   }
     82 
     83   public class Client
     84   {
     85     public void TestCase1()
     86     {
     87       var aggregate = new ConcreteAggregate();
     88       aggregate[0] = "Apple";
     89       aggregate[1] = "Orange";
     90       aggregate[2] = "Strawberry";
     91 
     92       var iterator = new ConcreteIterator(aggregate);
     93 
     94       object item = iterator.First();
     95       while (!iterator.IsDone())
     96       {
     97         Console.WriteLine(item);
     98         item = iterator.MoveNext();
     99       }
    100     }
    101   }
    102 }

    实现方式(二):实现 IEnumerable 中序遍历二叉树。

      1   /// <summary>
      2   /// 二叉树节点
      3   /// </summary>
      4   /// <typeparam name="T">The item type</typeparam>
      5   public class BinaryTreeNode<T>
      6   {
      7     #region Constructors
      8 
      9     /// <summary>
     10     /// 二叉树节点
     11     /// </summary>
     12     public BinaryTreeNode()
     13     {
     14     }
     15 
     16     /// <summary>
     17     /// 二叉树节点
     18     /// </summary>
     19     /// <param name="value">节点中的值</param>
     20     public BinaryTreeNode(T value)
     21     {
     22       this.Value = value;
     23     }
     24 
     25     /// <summary>
     26     /// 二叉树节点
     27     /// </summary>
     28     /// <param name="value">节点中的值</param>
     29     /// <param name="parent">节点的父节点</param>
     30     public BinaryTreeNode(T value, BinaryTreeNode<T> parent)
     31     {
     32       this.Value = value;
     33       this.Parent = parent;
     34     }
     35 
     36     /// <summary>
     37     /// 二叉树节点
     38     /// </summary>
     39     /// <param name="value">节点中的值</param>
     40     /// <param name="parent">节点的父节点</param>
     41     /// <param name="left">节点的左节点</param>
     42     /// <param name="right">节点的右节点</param>
     43     public BinaryTreeNode(T value, 
     44       BinaryTreeNode<T> parent, 
     45       BinaryTreeNode<T> left, 
     46       BinaryTreeNode<T> right)
     47     {
     48       this.Value = value;
     49       this.Right = right;
     50       this.Left = left;
     51       this.Parent = parent;
     52     }
     53 
     54     #endregion
     55 
     56     #region Properties
     57 
     58     /// <summary>
     59     /// 节点值
     60     /// </summary>
     61     public T Value { get; set; }
     62 
     63     /// <summary>
     64     /// 父节点
     65     /// </summary>
     66     public BinaryTreeNode<T> Parent { get; set; }
     67 
     68     /// <summary>
     69     /// 左节点
     70     /// </summary>
     71     public BinaryTreeNode<T> Left { get; set; }
     72 
     73     /// <summary>
     74     /// 右节点
     75     /// </summary>
     76     public BinaryTreeNode<T> Right { get; set; }
     77 
     78     /// <summary>
     79     /// 是否为根节点
     80     /// </summary>
     81     public bool IsRoot { get { return Parent == null; } }
     82 
     83     /// <summary>
     84     /// 是否为叶子节点
     85     /// </summary>
     86     public bool IsLeaf { get { return Left == null && Right == null; } }
     87 
     88     /// <summary>
     89     /// 是否为可访问的
     90     /// </summary>
     91     internal bool Visited { get; set; }
     92 
     93     #endregion
     94 
     95     #region Public Overridden Functions
     96 
     97     /// <summary>
     98     /// Returns a <see cref="System.String"/> that represents this instance.
     99     /// </summary>
    100     /// <returns>
    101     /// A <see cref="System.String"/> that represents this instance.
    102     /// </returns>
    103     public override string ToString()
    104     {
    105       return Value.ToString();
    106     }
    107 
    108     #endregion
    109   }
      1   /// <summary>
      2   /// 二叉树
      3   /// </summary>
      4   /// <typeparam name="T">二叉树中节点内容类型</typeparam>
      5   [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
      6   public class BinaryTree<T> : ICollection<T>, IEnumerable<T> where T : IComparable<T>
      7   {
      8     #region Constructor
      9 
     10     /// <summary>
     11     /// 二叉树
     12     /// </summary>
     13     public BinaryTree()
     14     {
     15       NumberOfNodes = 0;
     16     }
     17 
     18     /// <summary>
     19     /// 二叉树
     20     /// </summary>
     21     /// <param name="root">二叉树根节点</param>
     22     public BinaryTree(BinaryTreeNode<T> root)
     23       : this()
     24     {
     25       this.Root = root;
     26     }
     27 
     28     #endregion
     29 
     30     #region Properties
     31 
     32     /// <summary>
     33     /// 树的根节点
     34     /// </summary>
     35     public BinaryTreeNode<T> Root { get; set; }
     36 
     37     /// <summary>
     38     /// 树中节点的数量
     39     /// </summary>
     40     protected int NumberOfNodes { get; set; }
     41 
     42     /// <summary>
     43     /// 树是否为空
     44     /// </summary>
     45     public bool IsEmpty { get { return Root == null; } }
     46 
     47     /// <summary>
     48     /// 获取树中节点的最小值
     49     /// </summary>
     50     public T MinValue
     51     {
     52       get
     53       {
     54         if (IsEmpty)
     55           return default(T);
     56 
     57         BinaryTreeNode<T> minNode = Root;
     58         while (minNode.Left != null)
     59           minNode = minNode.Left;
     60 
     61         return minNode.Value;
     62       }
     63     }
     64 
     65     /// <summary>
     66     /// 获取树中节点的最大值
     67     /// </summary>
     68     public T MaxValue
     69     {
     70       get
     71       {
     72         if (IsEmpty)
     73           return default(T);
     74 
     75         BinaryTreeNode<T> maxNode = Root;
     76         while (maxNode.Right != null)
     77           maxNode = maxNode.Right;
     78 
     79         return maxNode.Value;
     80       }
     81     }
     82 
     83     #endregion
     84 
     85     #region IEnumerable<T> Members
     86 
     87     /// <summary>
     88     /// Returns an enumerator that iterates through the collection.
     89     /// </summary>
     90     /// <returns>
     91     /// A <see cref="T:System.Collections.Generic.IEnumerator`1"></see> 
     92     /// that can be used to iterate through the collection.
     93     /// </returns>
     94     public IEnumerator<T> GetEnumerator()
     95     {
     96       foreach (BinaryTreeNode<T> node in Traverse(Root))
     97       {
     98         yield return node.Value;
     99       }
    100     }
    101 
    102     #endregion
    103 
    104     #region IEnumerable Members
    105 
    106     /// <summary>
    107     /// Returns an enumerator that iterates through a collection.
    108     /// </summary>
    109     /// <returns>
    110     /// An <see cref="T:System.Collections.IEnumerator"/> 
    111     /// object that can be used to iterate through the collection.
    112     /// </returns>
    113     IEnumerator IEnumerable.GetEnumerator()
    114     {
    115       foreach (BinaryTreeNode<T> node in Traverse(Root))
    116       {
    117         yield return node.Value;
    118       }
    119     }
    120 
    121     #endregion
    122 
    123     #region ICollection<T> Members
    124 
    125     /// <summary>
    126     /// 新增节点
    127     /// </summary>
    128     /// <param name="item">The object to add to the 
    129     /// <see cref="T:System.Collections.Generic.ICollection`1"></see>.</param>
    130     /// <exception cref="T:System.NotSupportedException">The 
    131     /// <see cref="T:System.Collections.Generic.ICollection`1"></see> 
    132     /// is read-only.</exception>
    133     public void Add(T item)
    134     {
    135       if (Root == null)
    136       {
    137         Root = new BinaryTreeNode<T>(item);
    138         ++NumberOfNodes;
    139       }
    140       else
    141       {
    142         Insert(item);
    143       }
    144     }
    145 
    146     /// <summary>
    147     /// 清除树
    148     /// </summary>
    149     public void Clear()
    150     {
    151       Root = null;
    152     }
    153 
    154     /// <summary>
    155     /// 树中是否包含此节点
    156     /// </summary>
    157     /// <param name="item">The object to locate in the 
    158     /// <see cref="T:System.Collections.Generic.ICollection`1"></see>.</param>
    159     /// <returns>
    160     /// true if item is found in the 
    161     /// <see cref="T:System.Collections.Generic.ICollection`1"></see>; otherwise, false.
    162     /// </returns>
    163     public bool Contains(T item)
    164     {
    165       if (IsEmpty)
    166         return false;
    167 
    168       BinaryTreeNode<T> currentNode = Root;
    169       while (currentNode != null)
    170       {
    171         int comparedValue = currentNode.Value.CompareTo(item);
    172         if (comparedValue == 0)
    173           return true;
    174         else if (comparedValue < 0)
    175           currentNode = currentNode.Left;
    176         else
    177           currentNode = currentNode.Right;
    178       }
    179 
    180       return false;
    181     }
    182 
    183     /// <summary>
    184     /// 将树中节点拷贝至目标数组
    185     /// </summary>
    186     /// <param name="array">The array.</param>
    187     /// <param name="arrayIndex">Index of the array.</param>
    188     public void CopyTo(T[] array, int arrayIndex)
    189     {
    190       T[] tempArray = new T[NumberOfNodes];
    191       int counter = 0;
    192       foreach (T value in this)
    193       {
    194         tempArray[counter] = value;
    195         ++counter;
    196       }
    197       Array.Copy(tempArray, 0, array, arrayIndex, Count);
    198     }
    199 
    200     /// <summary>
    201     /// 树中节点的数量
    202     /// </summary>
    203     public int Count
    204     {
    205       get { return NumberOfNodes; }
    206     }
    207 
    208     /// <summary>
    209     /// 树是否为只读
    210     /// </summary>
    211     public bool IsReadOnly
    212     {
    213       get { return false; }
    214     }
    215 
    216     /// <summary>
    217     /// 移除节点
    218     /// </summary>
    219     /// <param name="item">节点值</param>
    220     /// <returns>是否移除成功</returns>
    221     public bool Remove(T item)
    222     {
    223       BinaryTreeNode<T> node = Find(item);
    224       if (node == null)
    225         return false;
    226 
    227       List<T> values = new List<T>();
    228       foreach (BinaryTreeNode<T> l in Traverse(node.Left))
    229       {
    230         values.Add(l.Value);
    231       }
    232       foreach (BinaryTreeNode<T> r in Traverse(node.Right))
    233       {
    234         values.Add(r.Value);
    235       }
    236 
    237       if (node.Parent.Left == node)
    238       {
    239         node.Parent.Left = null;
    240       }
    241       else
    242       {
    243         node.Parent.Right = null;
    244       }
    245 
    246       node.Parent = null;
    247 
    248       foreach (T v in values)
    249       {
    250         this.Add(v);
    251       }
    252 
    253       return true;
    254     }
    255 
    256     #endregion
    257 
    258     #region Private Functions
    259 
    260     /// <summary>
    261     /// 查找指定值的节点
    262     /// </summary>
    263     /// <param name="value">指定值</param>
    264     /// <returns>
    265     /// 指定值的节点
    266     /// </returns>
    267     protected BinaryTreeNode<T> Find(T value)
    268     {
    269       foreach (BinaryTreeNode<T> node in Traverse(Root))
    270         if (node.Value.Equals(value))
    271           return node;
    272       return null;
    273     }
    274 
    275     /// <summary>
    276     /// 遍历树
    277     /// </summary>
    278     /// <param name="node">遍历搜索的起始节点</param>
    279     /// <returns>
    280     /// The individual items from the tree
    281     /// </returns>
    282     [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
    283     protected IEnumerable<BinaryTreeNode<T>> Traverse(BinaryTreeNode<T> node)
    284     {
    285       // 遍历左子树
    286       if (node.Left != null)
    287       {
    288         foreach (BinaryTreeNode<T> left in Traverse(node.Left))
    289           yield return left;
    290       }
    291 
    292       // 中序遍历二叉树, 顺序是 左子树,根,右子树
    293       yield return node;
    294 
    295       // 遍历右子树
    296       if (node.Right != null)
    297       {
    298         foreach (BinaryTreeNode<T> right in Traverse(node.Right))
    299           yield return right;
    300       }
    301     }
    302 
    303     /// <summary>
    304     /// 插入节点
    305     /// </summary>
    306     /// <param name="value">插入的节点值</param>
    307     protected void Insert(T value)
    308     {
    309       // 从根节点开始比较
    310       BinaryTreeNode<T> currentNode = Root;
    311       
    312       while (true)
    313       {
    314         if (currentNode == null)
    315           throw new InvalidProgramException("The current tree node cannot be null.");
    316 
    317         // 比较当前节点与新节点的值
    318         int comparedValue = currentNode.Value.CompareTo(value);
    319         if (comparedValue < 0)
    320         {
    321           // 当前节点值小于新节点值
    322           if (currentNode.Left == null)
    323           {
    324             currentNode.Left = new BinaryTreeNode<T>(value, currentNode);
    325             ++NumberOfNodes;
    326             return;
    327           }
    328           else
    329           {
    330             currentNode = currentNode.Left;
    331           }
    332         }
    333         else if (comparedValue > 0)
    334         {
    335           // 当前节点值大于新节点值
    336           if (currentNode.Right == null)
    337           {
    338             currentNode.Right = new BinaryTreeNode<T>(value, currentNode);
    339             ++NumberOfNodes;
    340             return;
    341           }
    342           else
    343           {
    344             currentNode = currentNode.Right;
    345           }
    346         }
    347         else
    348         {
    349           // 当前节点值等于新节点值
    350           currentNode = currentNode.Right;
    351         }
    352       }
    353     }
    354 
    355     #endregion
    356   }

    实现方式(三):实现 BidirectionalConcurrentDictionary 双向并发字典。

      1 namespace IteratorPattern.Implementation3
      2 {
      3   /// <summary>
      4   /// 双值对
      5   /// </summary>
      6   /// <typeparam name="TFirst">第一个值的类型</typeparam>
      7   /// <typeparam name="TSecond">第二个值的类型</typeparam>
      8   [Serializable]
      9   public struct FirstSecondPair<TFirst, TSecond>
     10   {
     11     private TFirst first;
     12     private TSecond second;
     13 
     14     /// <summary>
     15     /// 第一个值
     16     /// </summary>
     17     public TFirst First
     18     {
     19       get
     20       {
     21         return this.first;
     22       }
     23     }
     24 
     25     /// <summary>
     26     /// 第二个值
     27     /// </summary>
     28     public TSecond Second
     29     {
     30       get
     31       {
     32         return this.second;
     33       }
     34     }
     35 
     36     /// <summary>
     37     /// 双值对
     38     /// </summary>
     39     /// <param name="first">第一个值</param>
     40     /// <param name="second">第二个值</param>
     41     public FirstSecondPair(TFirst first, TSecond second)
     42     {
     43       if (first == null)
     44         throw new ArgumentNullException("first");
     45       if (second == null)
     46         throw new ArgumentNullException("second");
     47 
     48       this.first = first;
     49       this.second = second;
     50     }
     51 
     52     /// <summary>
     53     /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
     54     /// </summary>
     55     /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
     56     /// <returns>
     57     ///   <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
     58     /// </returns>
     59     public override bool Equals(object obj)
     60     {
     61       if (obj == null)
     62         return false;
     63 
     64       FirstSecondPair<TFirst, TSecond> target = (FirstSecondPair<TFirst, TSecond>)obj;
     65       return this.First.Equals(target.First) && this.Second.Equals(target.Second);
     66     }
     67 
     68     /// <summary>
     69     /// Returns a hash code for this instance.
     70     /// </summary>
     71     /// <returns>
     72     /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
     73     /// </returns>
     74     public override int GetHashCode()
     75     {
     76       return base.GetHashCode();
     77     }
     78 
     79     /// <summary>
     80     /// Returns a <see cref="System.String"/> that represents this instance.
     81     /// </summary>
     82     /// <returns>
     83     /// A <see cref="System.String"/> that represents this instance.
     84     /// </returns>
     85     public override string ToString()
     86     {
     87       StringBuilder sb = new StringBuilder();
     88       sb.Append('[');
     89 
     90       if (this.First != null)
     91       {
     92         sb.Append(this.First.ToString());
     93       }
     94 
     95       sb.Append(", ");
     96 
     97       if (this.Second != null)
     98       {
     99         sb.Append(this.Second.ToString());
    100       }
    101 
    102       sb.Append(']');
    103 
    104       return sb.ToString();
    105     }
    106 
    107     /// <summary>
    108     /// Implements the operator ==.
    109     /// </summary>
    110     /// <param name="left">The left.</param>
    111     /// <param name="right">The right.</param>
    112     /// <returns>
    113     /// The result of the operator.
    114     /// </returns>
    115     public static bool operator ==(FirstSecondPair<TFirst, TSecond> left, FirstSecondPair<TFirst, TSecond> right)
    116     {
    117       if (((object)left == null) || ((object)right == null))
    118       {
    119         return false;
    120       }
    121 
    122       return left.Equals(right);
    123     }
    124 
    125     /// <summary>
    126     /// Implements the operator !=.
    127     /// </summary>
    128     /// <param name="left">The left.</param>
    129     /// <param name="right">The right.</param>
    130     /// <returns>
    131     /// The result of the operator.
    132     /// </returns>
    133     public static bool operator !=(FirstSecondPair<TFirst, TSecond> left, FirstSecondPair<TFirst, TSecond> right)
    134     {
    135       return !(left == right);
    136     }
    137   }
    138 
    139   public class BidirectionalConcurrentDictionary<TFirst, TSecond> : IEnumerable<FirstSecondPair<TFirst, TSecond>>
    140   {
    141     #region Fields
    142 
    143     private ConcurrentDictionary<TFirst, TSecond> firstToSecond = new ConcurrentDictionary<TFirst, TSecond>();
    144     private ConcurrentDictionary<TSecond, TFirst> secondToFirst = new ConcurrentDictionary<TSecond, TFirst>();
    145 
    146     #endregion
    147 
    148     #region Public Methods
    149 
    150     public void Add(TFirst first, TSecond second)
    151     {
    152       if (firstToSecond.ContainsKey(first) || secondToFirst.ContainsKey(second))
    153         throw new ArgumentException("Duplicate first or second");
    154 
    155       firstToSecond.Add(first, second);
    156       secondToFirst.Add(second, first);
    157     }
    158 
    159     public bool ContainsFirst(TFirst first)
    160     {
    161       return firstToSecond.ContainsKey(first);
    162     }
    163 
    164     public bool ContainsSecond(TSecond second)
    165     {
    166       return secondToFirst.ContainsKey(second);
    167     }
    168 
    169     public TSecond GetByFirst(TFirst first)
    170     {
    171       TSecond second;
    172       if (!firstToSecond.TryGetValue(first, out second))
    173         throw new KeyNotFoundException("Cannot find second by first.");
    174 
    175       return second;
    176     }
    177 
    178     public TFirst GetBySecond(TSecond second)
    179     {
    180       TFirst first;
    181       if (!secondToFirst.TryGetValue(second, out first))
    182         throw new KeyNotFoundException("Cannot find first by second.");
    183 
    184       return first;
    185     }
    186 
    187     public void RemoveByFirst(TFirst first)
    188     {
    189       TSecond second;
    190       if (!firstToSecond.TryGetValue(first, out second))
    191         throw new KeyNotFoundException("Cannot find second by first.");
    192 
    193       firstToSecond.Remove(first);
    194       secondToFirst.Remove(second);
    195     }
    196 
    197     public void RemoveBySecond(TSecond second)
    198     {
    199       TFirst first;
    200       if (!secondToFirst.TryGetValue(second, out first))
    201         throw new KeyNotFoundException("Cannot find first by second.");
    202 
    203       secondToFirst.Remove(second);
    204       firstToSecond.Remove(first);
    205     }
    206 
    207     public bool TryAdd(TFirst first, TSecond second)
    208     {
    209       if (firstToSecond.ContainsKey(first) || secondToFirst.ContainsKey(second))
    210         return false;
    211 
    212       firstToSecond.Add(first, second);
    213       secondToFirst.Add(second, first);
    214       return true;
    215     }
    216 
    217     public bool TryGetByFirst(TFirst first, out TSecond second)
    218     {
    219       return firstToSecond.TryGetValue(first, out second);
    220     }
    221 
    222     public bool TryGetBySecond(TSecond second, out TFirst first)
    223     {
    224       return secondToFirst.TryGetValue(second, out first);
    225     }
    226 
    227     public bool TryRemoveByFirst(TFirst first)
    228     {
    229       TSecond second;
    230       if (!firstToSecond.TryGetValue(first, out second))
    231         return false;
    232 
    233       firstToSecond.Remove(first);
    234       secondToFirst.Remove(second);
    235       return true;
    236     }
    237 
    238     public bool TryRemoveBySecond(TSecond second)
    239     {
    240       TFirst first;
    241       if (!secondToFirst.TryGetValue(second, out first))
    242         return false;
    243 
    244       secondToFirst.Remove(second);
    245       firstToSecond.Remove(first);
    246       return true;
    247     }
    248 
    249     public int Count
    250     {
    251       get { return firstToSecond.Count; }
    252     }
    253 
    254     public void Clear()
    255     {
    256       firstToSecond.Clear();
    257       secondToFirst.Clear();
    258     }
    259 
    260     #endregion
    261 
    262     #region IEnumerable<FirstSecondPair<TFirst,TSecond>> Members
    263 
    264     IEnumerator<FirstSecondPair<TFirst, TSecond>> IEnumerable<FirstSecondPair<TFirst, TSecond>>.GetEnumerator()
    265     {
    266       foreach (var item in firstToSecond)
    267       {
    268         yield return new FirstSecondPair<TFirst, TSecond>(item.Key, item.Value);
    269       }
    270     }
    271 
    272     #endregion
    273 
    274     #region IEnumerable Members
    275 
    276     IEnumerator IEnumerable.GetEnumerator()
    277     {
    278       foreach (var item in firstToSecond)
    279       {
    280         yield return new FirstSecondPair<TFirst, TSecond>(item.Key, item.Value);
    281       }
    282     }
    283 
    284     #endregion
    285   }
    286 
    287   public static class ConcurrentDictionaryExtensions
    288   {
    289     public static TValue Add<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> collection, TKey key, TValue @value)
    290     {
    291       TValue result = collection.AddOrUpdate(key, @value, (k, v) => { return @value; });
    292       return result;
    293     }
    294 
    295     public static TValue Update<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> collection, TKey key, TValue @value)
    296     {
    297       TValue result = collection.AddOrUpdate(key, @value, (k, v) => { return @value; });
    298       return result;
    299     }
    300 
    301     public static TValue Get<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> collection, TKey key)
    302     {
    303       TValue @value = default(TValue);
    304       collection.TryGetValue(key, out @value);
    305       return @value;
    306     }
    307 
    308     public static TValue Remove<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> collection, TKey key)
    309     {
    310       TValue @value = default(TValue);
    311       collection.TryRemove(key, out @value);
    312       return @value;
    313     }
    314   }
    315 }

    实现方式(四):实现 RoundRobin 循环列表。

     1 namespace IteratorPattern.Implementation4
     2 {
     3   /// <summary>
     4   /// 循环列表
     5   /// </summary>
     6   /// <typeparam name="T"></typeparam>
     7   public class RoundRobinCollection<T> : IEnumerable<T>
     8   {
     9     private T[] _items;
    10     private int _head;
    11 
    12     /// <summary>
    13     /// 循环列表
    14     /// </summary>
    15     /// <param name="items">供循环的列表项</param>
    16     public RoundRobinCollection(IEnumerable<T> items)
    17     {
    18       if (items == null || items.Count<T>() == 0)
    19       {
    20         throw new ArgumentException(
    21           "One or more items must be provided", "items");
    22       }
    23 
    24       // copy the list to ensure it doesn't change on us 
    25       // (and so we can lock() on our private copy) 
    26       _items = items.ToArray();
    27     }
    28 
    29     /// <summary>
    30     /// 获取循环器
    31     /// </summary>
    32     /// <returns></returns>
    33     public IEnumerator<T> GetEnumerator()
    34     {
    35       int currentHead;
    36 
    37       lock (_items)
    38       {
    39         currentHead = _head++;
    40 
    41         if (_head == _items.Length)
    42         {
    43           // wrap back to the start 
    44           _head = 0;
    45         }
    46       }
    47 
    48       // return results [current] ... [last] 
    49       for (int i = currentHead; i < _items.Length; i++)
    50       {
    51         yield return _items[i];
    52       }
    53 
    54       // return wrap-around (if any) [0] ... [current-1] 
    55       for (int i = 0; i < currentHead; i++)
    56       {
    57         yield return _items[i];
    58       }
    59     }
    60 
    61     /// <summary>
    62     /// 获取循环器
    63     /// </summary>
    64     /// <returns></returns>
    65     IEnumerator IEnumerable.GetEnumerator()
    66     {
    67       return this.GetEnumerator();
    68     }
    69   }
    70 }

    设计模式之美》为 Dennis Gao 发布于博客园的系列文章,任何未经作者本人同意的人为或爬虫转载均为耍流氓。

  • 相关阅读:
    天空卫士陆明:数据法在企业如何落地
    陈宏申:浅谈京东电商商品文案挖掘难点与优化实践
    陈胡:Apache SeaTunnel实现 非CDC数据抽取实践
    李阳:京东零售OLAP平台建设和场景实践
    李卓豪:网易数帆数据中台逻辑数据湖的实践
    苗大东:京东基于强化学习的电商搜索排序算法
    构建AR视频空间大数据平台(物联网及工业互联网、视频、AI场景识别)
    长连接长轮询
    Nacos数据模型
    漏桶和令牌桶的区别
  • 原文地址:https://www.cnblogs.com/gaochundong/p/design_pattern_iterator.html
Copyright © 2020-2023  润新知