Python设计模式

Python设计模式 - 组合模式

2020-02-21  本文已影响0人  jumo

"""

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

"""

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

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

"""

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)

上一篇下一篇

猜你喜欢

热点阅读