Python设计模式——组合模式
2015-03-11 09:28
405 查看
组合模式(Composite Pattern)可用来统合类体系中的这两种对象,一种对象能够包含体系中的其他对象,另一种为基本的单元对象,并不能包含其他对象。
(Python中其实很少使用到组合模式,因为采用
常规方法,我们先可以用两种基类来分别表示这两种类型的组件。
先让我们看看运行的结果:
其中main()函数中:
层次结构如图所示
其UML:
AbstractItem要求所有子类的对象明确是不是组合体,同时还要求子类对象必须可迭代。
SimpleItem类用来表示组合单元,也就是非组合体
AbstractCompositeItem作为CompositeItem的基类,它实现了组合体所需的添加,移除,迭代等功能
接下来就是组合体CompositeItem的具体实现:
这样就实现分别用两个类来表示组合体与非组合体了。但是这种方法导致我们创建了两个抽象类,两个具体类,接口也没有完全统一,如果我们再能忍受少许的额外开销也许将会更简单。
接下来我们使用一个类来表示组合体与非组合体,这二者接口完全一直,只是非组合体并不能使用某些接口
它的main函数
类的代码
这里定义了两个工厂方法(还记得之前的工厂模式吗?),其中
我们还可以在类外面创建这两个工厂方法来创建非组合体和组合体
定义组合体方法
打印
(Python中其实很少使用到组合模式,因为采用
dict就可以实现相同的功能)
常规方法,我们先可以用两种基类来分别表示这两种类型的组件。
先让我们看看运行的结果:
$0.40 Pencil $1.60 Ruler $0.20 Eraser $2.20 Pencil Set $0.40 Pencil $1.60 Ruler $0.20 Eraser $3.60 Boxed Pencil Set $1.00 Box $2.20 Pencil Set $0.40 Pencil $1.60 Ruler $0.20 Eraser $0.40 Pencil
其中main()函数中:
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.print()
层次结构如图所示
其UML:
AbstractItem要求所有子类的对象明确是不是组合体,同时还要求子类对象必须可迭代。
class AbstractItem(object): __metaclass__=abc.ABCMeta @abc.abstractproperty def composite(self): pass def __iter__(self): return iter([])
SimpleItem类用来表示组合单元,也就是非组合体
class SimpleItem(AbstractItem): def __init__(self, name, price=0.00): self.name = name self.price = price @property def composite(self): """ 表明是非组合体 """ return False def print(self, indent="", file=sys.stdout): print("{}${:.2f} {}".format(indent, self.price, self.name), file=file)
AbstractCompositeItem作为CompositeItem的基类,它实现了组合体所需的添加,移除,迭代等功能
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)
接下来就是组合体CompositeItem的具体实现:
class CompositeItem(AbstractCompositeItem): def __init__(self, name, *items): super().__init__(*items) self.name = name @property def composite(self): """ 确认是组合体 """ return True @property def price(self): return sum(item.price for item in self) def print(self, indent="", file=sys.stdout): print("{}${:.2f} {}".format(indent, self.price, self.name), file=file) for child in self: child.print(indent + " ")
这样就实现分别用两个类来表示组合体与非组合体了。但是这种方法导致我们创建了两个抽象类,两个具体类,接口也没有完全统一,如果我们再能忍受少许的额外开销也许将会更简单。
接下来我们使用一个类来表示组合体与非组合体,这二者接口完全一直,只是非组合体并不能使用某些接口
它的main函数
def main(): pencil = Item.create("Pencil", 0.40) ruler = Item.create("Ruler", 1.60) eraser = make_item("Eraser", 0.20) pencilSet = Item.compose("Pencil Set", pencil, ruler, eraser) box = Item.create("Box", 1.00) boxedPencilSet = make_composite("Boxed Pencil Set", box, pencilSet) boxedPencilSet.add(pencil) for item in (pencil, ruler, eraser, pencilSet, boxedPencilSet): item.print() assert not pencil.composite pencil.add(eraser, box) assert pencil.composite pencil.print() pencil.remove(eraser) assert pencil.composite pencil.remove(box) assert not pencil.composite pencil.print()
类的代码
class Item: def __init__(self, name, *items, price=0.00): """ 将items加入children 可以依据children判断是否是组合体 """ self.name = name self.price = price self.children = [] if items: self.add(*items)
这里定义了两个工厂方法(还记得之前的工厂模式吗?),其中
create创建非组合体,
compose创建组合体
@classmethod def create(Class, name, price): return Class(name, price=price) @classmethod def compose(Class, name, *items): return Class(name, *items)
我们还可以在类外面创建这两个工厂方法来创建非组合体和组合体
def make_item(name, price): return Item(name, price=price) def make_composite(name, *items): return Item(name, *items)
composite判断是否是组合体
@property 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 print(self, indent="", file=sys.stdout): print("{}${:.2f} {}".format(indent, self.price, self.name), file=file) for child in self: child.print(indent + " ")
相关文章推荐
- 设计模式-结构型模式,python组合模式
- NET常用设计模式——组合模式
- 设计模式之python版(四)代理模式
- 设计模式之python版(二)--策略模式
- 设计模式之python版(一)--工厂模式
- Python设计模式系列之一: 用模式改善软件设计
- <读书笔记> Thinking in python (Python 设计模式) 1. Singlton的c++与python的实现
- Head First 设计模式——装饰器(Decorator Pattern)——Python实现
- Head First 设计模式——观察者模式(Observer Pattern)——Python实现(2)
- 【设计模式】观察者模式(observer)c#/python实现
- <读书笔记> Thinking in python (Python 设计模式) 2. Templated Method
- python设计模式(1)-Simple Factory(Static Factory)(简单工厂)
- Python设计模式系列之一: 用模式改善软件设计
- Python - 设计模式 - Adapter Pattern
- 设计模式之六——组合模式
- Python设计模式1--工厂方法模式
- Python设计模式系列之一: 用模式改善软件设计(转载)
- Head First 设计模式—Python实现
- Python 与设计模式 1
- Python设计模式系列之一: 用模式改善软件设计