Python的结构型设计模式之组合模式

来源:互联网 发布:男生形象改造 知乎 编辑:程序博客网 时间:2024/05/25 16:37
组合模式,可用来统合类体系中的两种对象:一种对象能够包含体系中的其他对象,另一种不能。前者叫“组合体”,后者叫“非组合体”
白话来说,好几个东西,都是来自于同一个祖父,但是有些却结合了在一起,而结合在一起的它们,又可以用一个父亲来表示。这个父亲还能继续结合其他的小东西。
今天这个例子确实是很确切了:
大箱子
盒子 铅笔盒 铅笔

铅笔   橡皮   尺子

第一种方法呢,就是:
大箱子:基类A
单个物品(盒子、铅笔、尺子):A的子类
铅笔盒(曰组合体): 继承基类的基类的子类

代码如下,反正我是觉得,这不就是抽象类 + 继承嘛。

class AbstractItem(metaclass=abc.ABCMeta):    @abc.abstractproperty    def composite(self):        pass    def __iter__(self):        return iter([])class SimpleItem(AbstractItem):    def __init__(self, name, price=0.00):        self.name = name        self.price = price    @property    def composite(self):        return False    def printf(self, indent=""):        print ("{}${:.2f} {}".format(indent, self.price, self.name))class AbstractCompositeItem(AbstractItem):    def __init__(self, *items):        self.children = []        if items:            self.add(*items)    def add(self, first, *items):        self.children.append(first)        if items:            self.children.extend(items)    def remove(self, item):        self.children.remove(item)    def __iter__(self):        return iter(self.children)class CompositeItem(AbstractCompositeItem):    def __init__(self, name, *items):        super.__init__(*items)        self.name = name    @property    def composite(self):        return True    @property    def price(self):        print sum(item.price for item in self)    def printf(self, indent=""):        print ("{}${:.2f} {]".format(indent, self.price, self.name))        for child in self:            child.printf(indent + "     ")def main():    pencil = SimpleItem("Pencil", 0.40)    ruler = SimpleItem("Ruler", 1.60)    eraser = SimpleItem("Eraser", 0.20)    pencilSet = CompositeItem("Pencil Set", pencil, ruler, eraser)    box = SimpleItem("Box", 1.00)    boxedPencilSet = CompositeItem("Boxed Pencil Set", box, pencilSet)    boxedPencilSet.add(pencil)    for item in (pencil, ruler, eraser, pencilSet, boxedPencilSet):        item.printf()

而第二种方法呢,我觉得就是在初始化的时做了点小技巧,然后就可以用一个类来全部表示咯

class Item:    def __init__(self, name, price=0.00, *items):        self.name = name        self.price = price        self.children = []        if items:            self.add(*items)    @classmethod    def create(Class, name, price):        return Item(name, price=price)    @classmethod    def compose(Class, name, *items):        return Item(name, *items)    def composite(self):        return bool(self.children)    def add(self, first, *items):        self.children.extend(itertools.chain((first,), items))    def remove(self, item):        self.children.remove(item)    def __iter__(self):        return iter(self.children)    @property    def price(self):        return (sum(item.price for item in self) if self.children else self.__price)    @price.setter    def price(self, price):        self.__price = price    def printf(self, indent=""):        print ("{}${:.2f} {]".format(indent, self.price, self.name))        for child in self:            child.printf(indent + "     ")
就是在初始化的时候给参数加上一个可以存组合体的 [],然后在方法里面加上一个 compose 即可
Item.create("Ruler", 1.60)
Item.compose("Pencil Set", pencil, ruler, eraser)

如果说第一种方法是我们比较常用的,那么第二种模式确实能方便点,不用多创建其他类,只用一个类就可以。

0 0