Pattern Tips 之四
作者:温昱
感谢:《设计模式》一书的作者Gamma,Helm,Johnson和Vilssides,译者李英军等
----------------------------------说明----------------------------
Composite,Decorator。它们都是Structural Patterns,它们的关系如下图所示:
----------------------------------Composite----------------------------
●Tip 1:关键字。Uniform,Tree,Recursive。
●Tip 2:图。
可以看到,图中除了多个“泛化关系”之外,就只剩下一个“聚合关系”了(不是“组成关系”),而恰恰是这个“聚合关系”是至关重要的,它就是著名的“反向包含”(Reverse Contain)。
●Tip 3:实现与使用。
对“Architect或Achitecture工程师”,应注意Composite Class有一个member var存放Children,而且这个member var是个Container而不是个Manager,即单个Child的实例化工作Composite是不管的。
class CompositeEquipment : public Equipment { public: virtual ~CompositeEquipment(); virtual Watt Power(); virtual Currency NetPrice(); virtual Currency DiscountPrice(); virtual void Add(Equipment*); virtual void Remove(Equipment*); virtual Iterator* CreateIterator(); protected: CompositeEquipment(const char*); private: List <Equipment *> _equipment; /////////// note here, a list of children };所有Component的实例化工作将由“Application工程师”负责。
在MFC中,有OS维护的window tree就是最典型的例子。
●Tip 4:优点。Makes the client simple。Clients can treat composite structures and individual objects uniformly,这就是抽象的力量,一个抽象节点Component带来的简单好处。当然,这当中,也不能忘了Recursive算法的贡献,Recursive算法一向以代码简短、逻辑清楚著称。
●Tip 5:支持变化。
Makes it easier to add new kinds of components. Newly defined Composite or Leaf subclasses work automatically with existing structures and client code. Clients don''t have to be changed for new Component classes.
图中的黄色Class是后来扩充的,你可以扩充New Leaf,也可以扩充New Composite。
●Tip 6:局限性。Maximizing the Component interface。
One of the goals of the Composite pattern is to make clients unaware of the specific Leaf or Composite classes they''re using. To attain this goal, the Component class should define as many common operations for Composite and Leaf classes as possible. The Component class usually provides default implementations for these operations, and Leaf and Composite subclasses will override them.
Defining the child management interface at the root of the class hierarchy gives you transparency, because you can treat all components uniformly. It costs you safety, however, because clients may try to do meaningless things like add and remove objects from leaves.
----------------------------------Decorator----------------------------
●Tip 1:关键字。forward,before forwarding,after forwarding。
●Tip 2:图。
●Tip 3:实现和使用。是一个退化的Composite,这一点充份表现在member var由一个Container退化成一个Node Pointer。
class Decorator : public VisualComponent { public: Decorator(VisualComponent*); virtual void Draw(); virtual void Resize(); // ... private: VisualComponent* _component; /////// note here, a point to leaf or decorator };在ET++中,CStream。。。
●Tip 4:优点。
More flexibility than static inheritance.Furthermore, providing different Decorator classes for a specific Component class lets you mix and match responsibilities. Decorators also make it easy to add a property twice. For example, to give a TextView a double border, simply attach two BorderDecorators. Inheriting from a Border class twice is error-prone at best.
●Tip 5:局限性。When the Component class is intrinsically heavyweight, using the Decorator pattern is too costly to apply.
----------------------------------Decorator and Composite----------------------------
●Tip 1:Composite : A decorator can be viewed as a degenerate composite with only one component.
●Tip 2:Decorator is often used with Composite.
When decorators and composites are used together, they will usually have a common parent class. So decorators will have to support the Component interface with operations like Add, Remove, and GetChild.
However, a decorator adds additional responsibilities──it isn''t intended for object aggregation.
----------------------------------Builder and Composite----------------------------
●Tip 1:A Composite is what the builder often builds。
很显然,Builder and Composite谁也不是谁的超集。证明:一方面,Composite提供Component的递归包含,而Builder不提供;另一方面,Builder提供create和assemble双重服务, 而Composite只提供assemble服务。
我个人的理解,使用Builder模式的Composite模式,就是提供了create和assemble双重服务,使得“Application工程师”不必担负“实例化Component”的任务。