组合模式(python版) 兼有 目录结构(多叉树的生成)


什么是组合模式?


组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。掌握组合模式的重点是要理解清楚 “部分/整体” 还有 ”单个对象“ 与 “组合对象” 的含义。


组合模式UML图

这里写图片描述


组合模式python实现


下面考虑一个目录的例子:

题目:

一个目录,目录下可以有子目录和具体文件(叶节点),子目录和目录的行为方法相同对外界有相同的接口

题目分析:

对于子目录和目录,即整体和部分可以被一致对待。
当需求中是体现部分与整体层次结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象时,就应该考虑组合模式。组合模式是将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使用户对单个对象和组合对象的使用具有一致性。

python 代码实现

Catalog类:

class Catalog():
    def __init__(self,name):
        self.name = name              #目录的名字
        self.children = []            #子节点列表

    #向该目录下添加一个目录或叶节点
    def add(self,leaf):               
        self.children.append(leaf)

    #以字符串为名字的节点是否在子节点列表中,若在返回下标,不在返回-1
    def name_in(self,name):           
        for i in range(len(self.children)):
            child = self.children[i]
            if name == child.name:
                return i
        return -1

    #删除该目录下的以leaf_name为名字的子节点,若无抛出异常
    def delete(self,leaf_name):
        index = self.name_in(leaf_name)
        if index >= 0:
            del self.children[index]
        else:
            raise Exception("Catalog without the deleted items")

    #展示树形结构
    def display(self,depth):
        print '-'*depth + self.name
        for child in self.children:
            child.display(depth+2)

Leaf类:

class Leaves(Catalog):
    def __init__(self,name='',value=''):
        self.name = name
        self.children = []
        self.value = value              #叶节点的值

    #若向叶节点添加目录或叶节点抛出异常
    def add(self,leaf):
        raise Exception("Leaf nodes can't insert catalog")

    #想在叶节点下访问子节点列表,抛出异常
    def name_in(self,name):
        raise Exception("Leaf nodes without subcatalog")

    #想在叶节点下访问子节点列表,抛出异常
    def delete(self,leaf_name):
        raise Exception("Leaf nodes without subcatalog")

测试:

>>> from Catalog import Catalog,Leaves
>>> root = Catalog("root")
>>> SubCatalog1 = Catalog("SubCatalog1")
>>> SubCatalog2 = Catalog("SubCatalog2")
>>> leaf1 = Leaves("leaf1","1")
>>> leaf2 = Leaves("leaf2","2")
>>> leaf3 = Leaves("leaf3","3")
>>> leaf4 = Leaves("leaf4","4")
>>> root.add(SubCatalog1)
>>> root.add(SubCatalog2)
>>> root.add(leaf1)
>>> SubCatalog1.add(leaf2)
>>> SubCatalog1.add(leaf3)
>>> SubCatalog2.add(leaf4)
>>> root.display(0)

root
--SubCatalog1
----leaf2
----leaf3
--SubCatalog2
----leaf4
--leaf1

>>> SubCatalog2.delete("leaf4")
>>> root.display(0)

root
--SubCatalog1
----leaf2
----leaf3
--SubCatalog2
--leaf1

>>> SubCatalog2.delete("leaf4")

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "Catalog.py", line 20, in delete
    raise Exception("Catalog without the deleted items")
Exception: Catalog without the deleted items

>>> root.display(0)

root
--SubCatalog1
----leaf2
----leaf3
--SubCatalog2
--leaf1

>>> new_leaf1 = Leaves("new_leaf1","1")
>>> new_leaf2 = Leaves("new_leaf2","2")
>>> leaf1.add(new_leaf1)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "Catalog.py", line 31, in add
    raise Exception("Leaf nodes can't insert catalog")
Exception: Leaf nodes can't insert catalog

>>> leaf1.delete("new_leaf1")

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "Catalog.py", line 35, in delete
    raise Exception("Leaf nodes without subcatalog")
Exception: Leaf nodes without subcatalog

>>> SubCatalog2.add(new_leaf1)
>>> SubCatalog2.add(new_leaf2)
>>> root.display(0)

root
--SubCatalog1
----leaf2
----leaf3
--SubCatalog2
----new_leaf1
----new_leaf2
--leaf1

>>> root.delete("SubCatalog2")
>>> root.display(0)

root
--SubCatalog1
----leaf2
----leaf3
--leaf1

透明组合模式与安全组合模式

透明方式

在Component中声明所有用来管理子对象的方法,如Add()方法,delete()方法及name_in()方法,所有实现Component接口的子类都具备这些方法,这使得Component和子类具备一致的行为接口,使得对客户端无需区别树叶和树枝对象。

正由于我们的Composite和Leaf都具备一致的接口行为,但我们知道Leaf不应该具有Add(),delete()及name_in()方法,因为我们叶子节点不能再添加和移除节点了。

安全模式

在透明模式基础上把Component中声明所有用来管理子对象的方法移到Composite中,在Composite实现子对象的管理方法,那么Leaf就没有子对象管理方法,这使得Composite和Leaf的行为接口不一致,所以客户端在调用时要知道树叶和树枝对象存在。

两种组合模式各有好处,具体使用视情况而定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值