您的位置:首页 > 编程语言 > Python开发

Python设计模式(十八)【组合模式】

2016-08-30 15:44 302 查看

天空黑暗到一定程度,星辰就会熠熠生辉。

"""组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。"""

"""
一个类定义的组合对象,它可以用名称来存储分层使用的字典。

这个类是相同的分层字典,但它按名称提供方法来添加/访问/修改子元素,就像一个组合。

"""

def normalize(val):
""" 正常化一个特殊字符的字符串,以便它可以被用来作为一个Python对象一个属性
"""

if val.find('-') != -1:
val = val.replace('-', '_')

return val

def denormalize(val):
""" 非规范化一个字符串"""

if val.find('_') != -1:
val = val.replace('_', '-')

return val

class SpecialDict(dict):

"""
字典类,允许其键直接访问属性
"""

def __getattr__(self, name):

if name in self.__dict__:
return self.__dict__[name]
elif name in self:
return self.get(name)
else:
# 检查非规范化的名字
name = denormalize(name)
if name in self:
return self.get(name)
else:
raise AttributeError('没有属性名称 %s' % name)

def __setattr__(self, name, value):

if name in self.__dict__:
self.__dict__[name] = value
elif name in self:
self[name] = value
else:
# 检查非规范化的名字
name2 = denormalize(name)
if name2 in self:
self[name2] = value
else:
# 新属性
self[name] = value

class CompositeDict(SpecialDict):

"""一类像一个层次词典。
这个类是基于组合设计模式"""

ID = 0

def __init__(self, name=''):

if name:
self._name = name
else:
self._name = ''.join(('id#', str(self.__class__.ID)))
self.__class__.ID += 1

self._children = []
# 链接到父亲
self._father = None
self[self._name] = SpecialDict()

def __getattr__(self, name):

if name in self.__dict__:
return self.__dict__[name]
elif name in self:
return self.get(name)
else:
#  检查非规范化的名字
name = denormalize(name)
if name in self:
return self.get(name)
else:
#查看孩子列表
child = self.findChild(name)
if child:
return child
else:
attr = getattr(self[self._name], name)
if attr:
return attr

raise AttributeError('no attribute named %s' % name)

def isRoot(self):
""" Return 我是否根组件"""

# 如果我没有父母,我的根节点
return not self._father

def isLeaf(self):
""" Return 叶节点 """

# 我是一片叶节点,如果我没有孩子
return not self._children

def getName(self):
""" 返回ConfigInfo对象的名称 """

return self._name

def getIndex(self, child):
"""返回孩子ConfigInfo对象的'child'的索引"""

if child in self._children:
return self._children.index(child)
else:
return -1

def getDict(self):
""" 返回包含的词典"""

return self[self._name]

def getProperty(self, child, key):
""" 返回属性值"""

# 首先get孩子的字典
childDict = self.getInfoDict(child)
if childDict:
return childDict.get(key, None)

def setProperty(self, child, key, value):
"""
设置属性的“key”的值
"""

#首先get孩子的字典
childDict = self.getInfoDict(child)
if childDict:
childDict[key] = value

def getChildren(self):
""" 返回此对象的直接子列表 """

return self._children

def getAllChildren(self):
""" 返回此对象的所有子列表 """

l = []
for child in self._children:
l.append(child)
l.extend(child.getAllChildren())

return l

def getChild(self, name):
"""
用给定名称返回直接子对象
"""

for child in self._children:
if child.getName() == name:
return child

def findChild(self, name):
"""
从树返回(用给定的名称)子对象
"""

# 这将返回给定名称的第一个子对象
#任何其他具有类似名称的子对象不被考虑
for child in self.getAllChildren():
if child.getName() == name:
return child

def findChildren(self, name):
""" 从树返回给定名称的子对象列表"""

#这将返回给定名称的所有子项的列表,不论查询的深度
children = []

for child in self.getAllChildren():
if child.getName() == name:
children.append(child)

return children

def getPropertyDict(self):
""" 返回属性字典"""

d = self.getChild('__properties')
if d:
return d.getDict()
else:
return {}

def getParent(self):

return self._father

def __setChildDict(self, child):
"""
私有方法来设置子对象的'child'的字典在内部字典
"""

d = self[self._name]
d[child.getName()] = child.getDict()

def setParent(self, father):

self._father = father

def setName(self, name):
"""
设置此ConfigInfo对象的名称为'name'
"""

self._name = name

def setDict(self, d):
self[self._name] = d.copy()

def setAttribute(self, name, value):
self[self._name][name] = value

def getAttribute(self, name):
return self[self._name][name]

def addChild(self, name, force=False):
"""
添加一个新的子节点
如果可选标志“force”设置为True,子对象被覆盖,如果它已经存在。
该函数返回子对象,无论是新的或现有的
"""

if type(name) != str:
raise ValueError('Argument should be a string!')

child = self.getChild(name)
if child:
# print('Child %s present!' % name)
# 如果force==True 更换它
if force:
index = self.getIndex(child)
if index != -1:
child = self.__class__(name)
self._children[index] = child
child.setParent(self)

self.__setChildDict(child)
return child
else:
child = self.__class__(name)
child.setParent(self)

self._children.append(child)
self.__setChildDict(child)

return child

def addChild2(self, child):
"""
添加子对象'child'。如果它已经存在,它由缺省覆盖
"""
currChild = self.getChild(child.getName())
if currChild:
index = self.getIndex(currChild)
if index != -1:
self._children[index] = child
child.setParent(self)
# 未设置现有的子节点的父级
currChild.setParent(None)
del currChild

self.__setChildDict(child)
else:
child.setParent(self)
self._children.append(child)
self.__setChildDict(child)

if __name__ == "__main__":
window = CompositeDict('Window')
frame = window.addChild('Frame')
tfield = frame.addChild('Text Field')
tfield.setAttribute('size', '20')

btn = frame.addChild('Button1')
btn.setAttribute('label', '提交')

btn = frame.addChild('Button2')
btn.setAttribute('label', '浏览')

#print(window)
#print(window.Frame)
#print(window.Frame.Button1)
#print(window.Frame.Button2)
print(window.Frame.Button1.label)
print(window.Frame.Button2.label)


运行结果如图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: