结构图

 

Design Patterns(十七):Iterator Pattern--VB代码

角色

  • 迭代器(Iterator)角色:负责定义和遍历元素的接口。
  • 具体迭代器(Concrete Iterator)角色:实现迭代器接口,并要记录遍历中的当前位置。  
  • 容器(Container)角色:容器角色负责提供创建具体迭代器角色的接口。
  • 具体容器(Concrete Container)角色:具体容器角色实现创建具体迭代器角色的接口——这个具体迭代器角色于该容器的结构相关。

动机

  在软件构建过程中集合对象内部结构常常变化各异。但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部程序代码透明的访问其中包含的元素;  同时这种“透明遍历”也为“同一种算法在多种集合对象上进行操作” 提供了可能。
    使用面向对象技术将这种遍历机制抽象抽象为“迭代器”为“应对变化中的集合对象”提供了一种优雅的方式。

意图

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

示意性代码

 MainApp

    Sub Main()
        
Dim a As New ConcreteAggregate
        a(
0= "Item A"
        a(
1= "Item B"
        a(
2= "Item C"
        a(
3= "Item D"

        
'Create Iterator and provide aggregate
        Dim i As New ConcreteIterator(a)

        Console.WriteLine(
"Iterating over collection -----")

        
Dim item As Object = i.First()
        
While item IsNot Nothing
            Console.WriteLine(item)
            item 
= i.Next()
        
End While

        
'Wait for user 
        Console.Read()
    
End Sub

End Module

'"Aggregate" 
Public MustInherit Class Aggregate
    
Public MustOverride Function CreateIterator() As Iterator
End Class

'"ConcreteAggregate"
Public Class ConcreteAggregate
    
Inherits Aggregate
    
Private items As New ArrayList

    
Public Overrides Function CreateIterator() As Iterator
        
Return New ConcreteIterator(Me)
    
End Function

    
'Property 
    Public ReadOnly Property Count() As Integer
        
Get
            
Return items.Count
        
End Get
    
End Property

    
'Indexer
    Default Public Property Item(ByVal Index As IntegerAs Object
        
Get
            
Return items(Index)
        
End Get
        
Set(ByVal value As Object)
            items.Insert(Index, value)
        
End Set
    
End Property
End Class

'"Iterator"
Public MustInherit Class Iterator
    
Public MustOverride Function First() As Object
    
Public MustOverride Function [Next]() As Object
    
Public MustOverride Function IsDone() As Boolean
    
Public MustOverride Function CurrentItem() As Object
End Class

'"ConcreteIterator"
Public Class ConcreteIterator
    
Inherits Iterator
    
Private aggregate As ConcreteAggregate
    
Private current As Integer = 0

    
'Constructor 
    Public Sub New(ByVal aggregate As ConcreteAggregate)
        
Me.aggregate = aggregate
    
End Sub

    
Public Overrides Function First() As Object
        
Return aggregate(0)
    
End Function

    
Public Overrides Function [Next]() As Object
        
Dim ret As Object = Nothing
        
If current < aggregate.Count - 1 Then
            ret 
= aggregate(System.Threading.Interlocked.Increment(current))
        
End If
        
Return ret
    
End Function

    
Public Overrides Function CurrentItem() As Object
        
Return aggregate(current)
    
End Function

    
Public Overrides Function IsDone() As Boolean
        
Return current >= aggregate.Count
    
End Function
End Class

 

 一个实例

 下面的迭代器代码用来演示跳过某些项目遍历一个集合。

 MainApp
    Sub Main()
        
' Build a collection
        Dim collection As New Collection()
        collection(
0= New Item("Item 0")
        collection(
1= New Item("Item 1")
        collection(
2= New Item("Item 2")
        collection(
3= New Item("Item 3")
        collection(
4= New Item("Item 4")
        collection(
5= New Item("Item 5")
        collection(
6= New Item("Item 6")
        collection(
7= New Item("Item 7")
        collection(
8= New Item("Item 8")

        
' Create iterator
        Dim iterator As New Iterator(collection)

        
' Skip every other item
        iterator.[Step= 2

        Console.WriteLine(
"Iterating over collection:")

        
Dim item As Item = iterator.First()
        
While Not iterator.IsDone
            Console.WriteLine(item.Name)
            item 
= iterator.[Next]()
        
End While

        
' Wait for user
        Console.Read()
    
End Sub
End Module

Public Class Item
    
Private m_name As String

    
' Constructor
    Public Sub New(ByVal name As String)
        
Me.m_name = name
    
End Sub

    
' Property
    Public ReadOnly Property Name() As String
        
Get
            
Return m_name
        
End Get
    
End Property
End Class

' "Aggregate"
Public Interface IAbstractCollection
    
Function CreateIterator() As Iterator
End Interface

' "ConcreteAggregate"
Public Class Collection
    
Implements IAbstractCollection
    
Private items As New ArrayList()

    
Public Function CreateIterator() As Iterator Implements IAbstractCollection.CreateIterator
        
Return New Iterator(Me)
    
End Function

    
' Property
    Public ReadOnly Property Count() As Integer
        
Get
            
Return items.Count
        
End Get
    
End Property

    
' Indexer
    Default Public Property Item(ByVal index As IntegerAs Object
        
Get
            
Return items(index)
        
End Get
        
Set(ByVal value As Object)
            items.Add(value)
        
End Set
    
End Property
End Class

' "Iterator"
Public Interface IAbstractIterator
    
Function First() As Item
    
Function [Next]() As Item
    
ReadOnly Property IsDone() As Boolean
    
ReadOnly Property CurrentItem() As Item
End Interface

' "ConcreteIterator"
Public Class Iterator
    
Implements IAbstractIterator
    
Private collection As Collection
    
Private current As Integer = 0
    
Private m_step As Integer = 1

    
' Constructor
    Public Sub New(ByVal collection As Collection)
        
Me.collection = collection
    
End Sub

    
Public Function First() As Item Implements IAbstractIterator.First
        current 
= 0
        
Return TryCast(collection(current), Item)
    
End Function

    
Public Function [Next]() As Item Implements IAbstractIterator.[Next]
        current 
+= m_step
        
If Not IsDone Then
            
Return TryCast(collection(current), Item)
        
Else
            
Return Nothing
        
End If
    
End Function

    
' Properties
    Public Property [Step]() As Integer
        
Get
            
Return m_step
        
End Get
        
Set(ByVal value As Integer)
            m_step 
= value
        
End Set
    
End Property

    
Public ReadOnly Property CurrentItem() As Item Implements IAbstractIterator.CurrentItem
        
Get
            
Return TryCast(collection(current), Item)
        
End Get
    
End Property

    
Public ReadOnly Property IsDone() As Boolean Implements IAbstractIterator.IsDone
        
Get
            
Return current >= collection.Count
        
End Get
    
End Property
End Class

 

Iterator Pattern模式的几个要点:
   1、迭代抽象:访问一个聚合对象的内容而无需暴露它的内部信息。
   2、迭代多态:为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。
   3、迭代器健壮性考虑:遍历的同时更改迭代器所在的集合结构,会导致问题。

我的理解

封装集合对象的内部结构和遍历集合的算法,支持集合和算法的变化。

参考资料
《C#面向对象设计模式纵横谈系列课程(18)》     李建中老师

相关文章: