组合模式,可用来统合类体系中的两种对象:一种对象能够包含体系中的其他对象,另一种不能。前者叫“组合体”,后者叫“非组合体”
白话来说,好几个东西,都是来自于同一个祖父,但是有些却结合了在一起,而结合在一起的它们,又可以用一个父亲来表示。这个父亲还能继续结合其他的小东西。
今天这个例子确实是很确切了:
大箱子
盒子
铅笔盒
铅笔
铅笔 橡皮 尺子
第一种方法呢,就是:
大箱子:基类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)
如果说第一种方法是我们比较常用的,那么第二种模式确实能方便点,不用多创建其他类,只用一个类就可以。