美文网首页Python设计模式
Python设计模式 - 组合模式

Python设计模式 - 组合模式

作者: jumo | 来源:发表于2020-02-21 10:52 被阅读0次

    """

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

    """

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

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

    """

    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)

    相关文章

      网友评论

        本文标题:Python设计模式 - 组合模式

        本文链接:https://www.haomeiwen.com/subject/sgaqqhtx.html