Design Patterns(九):Composite Pattern--VB代码

  结构图

角色   
l    抽象构件(Component)角色:这是一个抽象角色,它给参加组合的对象定义出公共的接口及其默认行为,可以用来管理所有的子对象。在安全式的合成模式里,构件角色并不是定义出管理子对象的方法,这一定义由树枝构件对象给出。
l    树叶构件(Leaf)角色:树叶对象是没有下级子对象的对象,定义出参加组合的原始对象的行为。
l    树枝构件(Composite)角色:代表参加组合的有下级子对象的对象。树枝对象给出所有的管理子对象的方法。

动机
  客户代码过多地依赖于对象容器复杂的内部实现结构,对象容器内部实现结构(而非抽象接口)的变化将客户代码的频繁变化,带来了代码的维护性差、扩展性差等弊端。
  如何将“客户代码与复杂的对象容器结构”解耦?让对象容器自己来实现自身的复杂结构,从而使得客户代码就像处理简单对象一样来处理复杂的对象容器?

意图
    将对象组合成结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。

示意性代码

透明方式
    在Component里面声明所有用来管理子类对象的方法,包括add()、remove(),以及getChild()方法。这样做的好处是所有的构件类都有相同的接口。客户程序可以一致对待树叶类对象与合成类对象。不必关心所使用对象的内部构造。
透明方式
Imports System
Imports System.Collections

'MainApp test application
Public Class MainAppClass MainApp
    
Public Shared Sub Main()Sub Main()
        
'Create a tree structure
        Dim root As New Composite("root")
        root.Add(
New Leaf("Leaf A"))
        root.Add(
New Leaf("Leaf B"))

        
Dim com As New Composite("Composite X")
        com.Add(
New Leaf("Leaf XA"))
        com.Add(
New Leaf("Leaf XB"))
        root.Add(com)

        
'Add and remove a leaf
        Dim leaf As New Leaf("LeafD")
        root.Add(leaf)
        root.Remove(leaf)

        
'Recursively display tree
        root.Display(1)

        
'Wait for user
        Console.ReadLine()
    
End Sub

End Class


'"Component"
Public MustInherit Class ComponentClass Component
    
Protected name As String
    
' Constructor
    Public Sub New()Sub New(ByVal name As String)
        
Me.name = name
    
End Sub

    
Public MustOverride Sub Add()Sub Add(ByVal c As Component)
    
Public MustOverride Sub Remove()Sub Remove(ByVal c As Component)
    
Public MustOverride Sub Display()Sub Display(ByVal depth As Integer)
End Class


'"Composite"
Public Class CompositeClass Composite
    
Inherits Component
    
Private children As New ArrayList
    
Public Sub New()Sub New(ByVal name As String)
        
MyBase.new(name)
    
End Sub

    
Public Overrides Sub Add()Sub Add(ByVal c As Component)
        children.Add(c)
    
End Sub

    
Public Overrides Sub Remove()Sub Remove(ByVal c As Component)
        children.Remove(c)
    
End Sub

    
'Recursively display child nodes
    Public Overrides Sub Display()Sub Display(ByVal depth As Integer)
        
For Each c As Component In children
            c.Display(depth 
+ 2)
        
Next
    
End Sub

End Class


'"Leaf"
Public Class LeafClass Leaf
    
Inherits Component
    
' Constructors
    Public Sub New()Sub New(ByVal name As String)
        
MyBase.new(name)
    
End Sub

    
Public Overrides Sub Add()Sub Add(ByVal c As Component)
        Console.WriteLine(
"Cannot add to a leaf")
    
End Sub

    
Public Overrides Sub Remove()Sub Remove(ByVal c As Component)
        Console.WriteLine(
"Cannot remove from a leaf")
    
End Sub

    
Public Overrides Sub Display()Sub Display(ByVal depth As Integer)
        Console.WriteLine(
New String("-"c, depth) + name)
    
End Sub

End Class


安全方式
    在Composite类里面声明所有的用来管理子类对象的方法。这样的做法是安全的做法,因为树叶类型的对象根本就没有管理子类对象的方法,因此,如果客户端对树叶类对象使用这些方法时,程序会在编译时期出错。这个选择的缺点是不够透明,因为树叶类和合成类将具有不同的接口。
安全方式
Imports System
Imports System.Collections

'MainApp test application
Public Class MainAppClass MainApp
    
Public Shared Sub Main()Sub Main()
        
'Create a tree structure
        Dim root As New Composite("root")
        root.Add(
New Leaf("Leaf A"))
        root.Add(
New Leaf("Leaf B"))

        
Dim com As New Composite("Composite X")
        com.Add(
New Leaf("Leaf XA"))
        com.Add(
New Leaf("Leaf XB"))
        root.Add(com)

        
'Add and remove a leaf
        Dim leaf As New Leaf("LeafD")
        root.Add(leaf)
        root.Remove(leaf)

        
'Recursively display tree
        root.Display(1)

        
'Wait for user
        Console.ReadLine()
    
End Sub
End Class

'"Component"
Public MustInherit Class ComponentClass Component
    
Protected name As String
    
' Constructor
    Public Sub New()Sub New(ByVal name As String)
        
Me.name = name
    
End Sub
    
Public MustOverride Sub Display()Sub Display(ByVal depth As Integer)
End Class


'"Composite"
Public Class CompositeClass Composite
    
Inherits Component
    
Private children As New ArrayList
    
Public Sub New()Sub New(ByVal name As String)
        
MyBase.new(name)
    
End Sub

    
Public Sub Add()Sub Add(ByVal c As Component)
        children.Add(c)
    
End Sub

    
Public Sub Remove()Sub Remove(ByVal c As Component)
        children.Remove(c)
    
End Sub

    
'Recursively display child nodes
    Public Overrides Sub Display()Sub Display(ByVal depth As Integer)
        
For Each c As Component In children
            c.Display(depth 
+ 2)
        
Next
    
End Sub

End Class


'"Leaf"
Public Class LeafClass Leaf
    
Inherits Component
    
' Constructors
    Public Sub New()Sub New(ByVal name As String)
        
MyBase.new(name)
    
End Sub

    
Public Overrides Sub Display()Sub Display(ByVal depth As Integer)
        Console.WriteLine(
New String("-"c, depth) + name)
    
End Sub

End Class


实例
    该例子演示了依次向场景(root)中添加简单图形(RedLine,Blue Circle,Green Box)和复杂图形(Two Cricle)。最后同显示简单图形一样显示场景。
实例程序
Imports system
Imports system.collections


Public Class MainAppClass MainApp
    
Public Shared Sub Main()Sub Main()

        
'Create a tree structure
        Dim root As New CompositeElement("Picture")
        root.Add(
new PrimitiveElement("Red Line")
        root.Add(
new PrimitiveElement("Blue Circle")
        root.Add(
new PrimitiveElement("Green Box")

        
Dim comp As New CompositeElement("Two Cricle")
        comp.Add(
New PrimitiveElement("Black Circle"))
        comp.Add(
New PrimitiveElement("White Circle"))
        root.Add(comp)

        
'Add and remove a PrimitiveElement
        Dim pe As New PrimitiveElement("Yellow Line")
        root.Add(pe)
        root.Remove(pe)

        
'Recursivelly display nodes
        root.Display(1)

        
'Wait for user
        Console.Read()

    
End Sub

End Class


'"Component" Treenode
Public MustInherit Class DrawingElementClass DrawingElement
    
Protected name As String

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


    
Public MustOverride Sub Add()Sub Add(ByVal d As DrawingElement)
    
Public MustOverride Sub Remove()Sub Remove(ByVal d As DrawingElement)
    
Public MustOverride Sub Display()Sub Display(ByVal indent As Integer)
End Class


'"Leaf"
Public Class PrimitiveElementClass PrimitiveElement
    
Inherits DrawingElement

    
'Constructor
    Public Sub New()Sub New(ByVal name As String)
        
MyBase.new(name)
    
End Sub


    
Public Overrides Sub Add()Sub Add(ByVal c As DrawingElement)
        Console.WriteLine(
"Cannt add to a PrimitiveElement")
    
End Sub


    
Public Overrides Sub Remove()Sub Remove(ByVal c As DrawingElement)
        Console.WriteLine(
"Cannot remove from a PrimitiveElement")
    
End Sub


    
Public Overrides Sub Display()Sub Display(ByVal indent As Integer)
        Console.WriteLine(
New String("-"c, indent) & " " & name)
    
End Sub

End Class


'"Composite"
Public Class CompositeElementClass CompositeElement
    
Inherits DrawingElement
    
Private elements As New ArrayList

    
'Constructor
    Public Sub New()Sub New(ByVal name As String)
        
MyBase.new(name)
    
End Sub


    
Public Overrides Sub Add()Sub Add(ByVal d As DrawingElement)
        elements.Add(d)
    
End Sub


    
Public Overrides Sub Remove()Sub Remove(ByVal d As DrawingElement)
        elements.Remove(d)
    
End Sub


    
Public Overrides Sub Display()Sub Display(ByVal indent As Integer)

        Console.WriteLine(
New String("-"c, indent) & "" & name)

        
' Display each child element on this node
        For Each c As DrawingElement In elements
            c.Display(indent 
+ 2)
        
Next

    
End Sub

End Class


Composite模式的几个要点:
  1、Composite模式采用结构来实现普遍存在的对象容器,从而将“一对多”的关系转化为“一对一”的关系,使得客户代码可以一致地处理对象和对象容器,无需关心处理的是单个的对象,还是组合的对象容器。
  2、将“客户代码与复杂的对象容器结构”解耦是Composite模式的核心思想,解耦之后,客户代码将与纯粹的抽象接口--而非对象容器的内部实现结构--发生依赖关系,从而更能“应对变化”。
   3、Composite模式中,是将“Add和Remove等和对象容器相关的方法”定义在“表示抽象对象的Component类”中,还是将其定义在 “表示对象容器的 Composite类”中,是一个关乎“透明性”和“安全性”的两难问题,需要仔细权衡。这里有可能违背面向对象的“单一职责原则”,但是对于这种特殊结 构,这又是必须付出的代价。ASP.NET控件的实现在这方面为我们提供了一个很好的示范不。
  4、Composite模式在具体实现中,可以让父对象中的子对象反向追溯,如果父对象有频繁的遍历需求,可使用缓存技巧来改善效率。


我的理解
    当客户同时要使用结构相似的简单对象和复杂对象时(复杂对象包含简单对象),Composite把复杂对象简单化,使客户程序可以像使用简单对象一样使用复杂对象。

参考资料
《C#设计模式(11)-Composite Pattern》        吕震宇老师
《C#面向对象设计模式纵横谈系列课程(9)》     李建中老师

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值