// 客户端代码会通过基础接口与所有组件进行交互。这样一来,客户端代码便可同 // 时支持简单叶节点组件和复杂组件。 class ImageEditor is field all: CompoundGraphic
method load() is all = new CompoundGraphic() all.add(new Dot(1, 2)) all.add(new Circle(5, 3, 10)) // ...
// 将所需组件组合为复杂的组合组件。 method groupSelected(components: arrayof Graphic) is group = new CompoundGraphic() foreach (component in components) do group.add(component) all.remove(component) all.add(group) // 所有组件都将被绘制。 all.draw()
namespaceRefactoringGuru.DesignPatterns.Composite.Conceptual { // The base Component class declares common operations for both simple and // complex objects of a composition. abstractclassComponent { publicComponent() { }
// The base Component may implement some default behavior or leave it to // concrete classes (by declaring the method containing the behavior as // "abstract"). publicabstractstringOperation();
// In some cases, it would be beneficial to define the child-management // operations right in the base Component class. This way, you won't // need to expose any concrete component classes to the client code, // even during the object tree assembly. The downside is that these // methods will be empty for the leaf-level components. publicvirtualvoidAdd(Component component) { thrownew NotImplementedException(); }
// You can provide a method that lets the client code figure out whether // a component can bear children. publicvirtualboolIsComposite() { returntrue; } }
// The Leaf class represents the end objects of a composition. A leaf can't // have any children. // // Usually, it's the Leaf objects that do the actual work, whereas Composite // objects only delegate to their sub-components. classLeaf : Component { publicoverridestringOperation() { return"Leaf"; }
// The Composite class represents the complex components that may have // children. Usually, the Composite objects delegate the actual work to // their children and then "sum-up" the result. classComposite : Component { protected List<Component> _children = new List<Component>(); publicoverridevoidAdd(Component component) { this._children.Add(component); }
// The Composite executes its primary logic in a particular way. It // traverses recursively through all its children, collecting and // summing their results. Since the composite's children pass these // calls to their children and so forth, the whole object tree is // traversed as a result. publicoverridestringOperation() { int i = 0; string result = "Branch(";
foreach (Component component inthis._children) { result += component.Operation(); if (i != this._children.Count - 1) { result += "+"; } i++; } return result + ")"; } }
classClient { // The client code works with all of the components via the base // interface. publicvoidClientCode(Component leaf) { Console.WriteLine($"RESULT: {leaf.Operation()}\n"); }
// Thanks to the fact that the child-management operations are declared // in the base Component class, the client code can work with any // component, simple or complex, without depending on their concrete // classes. publicvoidClientCode2(Component component1, Component component2) { if (component1.IsComposite()) { component1.Add(component2); } Console.WriteLine($"RESULT: {component1.Operation()}"); } } classProgram { staticvoidMain(string[] args) { Client client = new Client();
// This way the client code can support the simple leaf // components... Leaf leaf = new Leaf(); Console.WriteLine("Client: I get a simple component:"); client.ClientCode(leaf);
// ...as well as the complex composites. Composite tree = new Composite(); Composite branch1 = new Composite(); branch1.Add(new Leaf()); branch1.Add(new Leaf()); Composite branch2 = new Composite(); branch2.Add(new Leaf()); tree.Add(branch1); tree.Add(branch2); Console.WriteLine("Client: Now I've got a composite tree:"); client.ClientCode(tree);
Console.Write("Client: I don't need to check the components classes even when managing the tree:\n"); client.ClientCode2(tree, leaf); } } }
Output.txt: 执行结果
1 2 3 4 5 6 7 8
Client: I get a simple component: RESULT: Leaf
Client: Now I've got a composite tree: RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf))
Client: I don't need to check the components classes even when managing the tree: RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf)+Leaf)
在 C++ 中使用模式
复杂度: ★★☆
流行度: ★★☆
使用实例: 组合模式在 C++ 代码中很常见, 常用于表示与图形打交道的用户界面组件或代码的层次结构。
#include<algorithm> #include<iostream> #include<list> #include<string> /** * The base Component class declares common operations for both simple and * complex objects of a composition. */ classComponent { /** * @var Component */ protected: Component *parent_; /** * Optionally, the base Component can declare an interface for setting and * accessing a parent of the component in a tree structure. It can also * provide some default implementation for these methods. */ public: virtual ~Component() {} voidSetParent(Component *parent){ this->parent_ = parent; } Component *GetParent()const{ returnthis->parent_; } /** * In some cases, it would be beneficial to define the child-management * operations right in the base Component class. This way, you won't need to * expose any concrete component classes to the client code, even during the * object tree assembly. The downside is that these methods will be empty for * the leaf-level components. */ virtualvoidAdd(Component *component){} virtualvoidRemove(Component *component){} /** * You can provide a method that lets the client code figure out whether a * component can bear children. */ virtualboolIsComposite()const{ returnfalse; } /** * The base Component may implement some default behavior or leave it to * concrete classes (by declaring the method containing the behavior as * "abstract"). */ virtual std::string Operation()const= 0; }; /** * The Leaf class represents the end objects of a composition. A leaf can't have * any children. * * Usually, it's the Leaf objects that do the actual work, whereas Composite * objects only delegate to their sub-components. */ classLeaf : public Component { public: std::string Operation()constoverride{ return"Leaf"; } }; /** * The Composite class represents the complex components that may have children. * Usually, the Composite objects delegate the actual work to their children and * then "sum-up" the result. */ classComposite : public Component { /** * @var \SplObjectStorage */ protected: std::list<Component *> children_;
public: /** * A composite object can add or remove other components (both simple or * complex) to or from its child list. */ voidAdd(Component *component)override{ this->children_.push_back(component); component->SetParent(this); } /** * Have in mind that this method removes the pointer to the list but doesn't * frees the * memory, you should do it manually or better use smart pointers. */ voidRemove(Component *component)override{ children_.remove(component); component->SetParent(nullptr); } boolIsComposite()constoverride{ returntrue; } /** * The Composite executes its primary logic in a particular way. It traverses * recursively through all its children, collecting and summing their results. * Since the composite's children pass these calls to their children and so * forth, the whole object tree is traversed as a result. */ std::string Operation()constoverride{ std::string result; for (const Component *c : children_) { if (c == children_.back()) { result += c->Operation(); } else { result += c->Operation() + "+"; } } return"Branch(" + result + ")"; } }; /** * The client code works with all of the components via the base interface. */ voidClientCode(Component *component){ // ... std::cout << "RESULT: " << component->Operation(); // ... }
/** * Thanks to the fact that the child-management operations are declared in the * base Component class, the client code can work with any component, simple or * complex, without depending on their concrete classes. */ voidClientCode2(Component *component1, Component *component2){ // ... if (component1->IsComposite()) { component1->Add(component2); } std::cout << "RESULT: " << component1->Operation(); // ... }
/** * This way the client code can support the simple leaf components... */
intmain(){ Component *simple = new Leaf; std::cout << "Client: I've got a simple component:\n"; ClientCode(simple); std::cout << "\n\n"; /** * ...as well as the complex composites. */
Component *tree = new Composite; Component *branch1 = new Composite;
Component *leaf_1 = new Leaf; Component *leaf_2 = new Leaf; Component *leaf_3 = new Leaf; branch1->Add(leaf_1); branch1->Add(leaf_2); Component *branch2 = new Composite; branch2->Add(leaf_3); tree->Add(branch1); tree->Add(branch2); std::cout << "Client: Now I've got a composite tree:\n"; ClientCode(tree); std::cout << "\n\n";
std::cout << "Client: I don't need to check the components classes even when managing the tree:\n"; ClientCode2(tree, simple); std::cout << "\n";
/** * The base Component class declares common operations for both simple and * complex objects of a composition. */ abstractclassComponent { /** * @var Component */ protected$parent;
/** * Optionally, the base Component can declare an interface for setting and * accessing a parent of the component in a tree structure. It can also * provide some default implementation for these methods. */ publicfunctionsetParent(Component $parent) { $this->parent = $parent; }
/** * In some cases, it would be beneficial to define the child-management * operations right in the base Component class. This way, you won't need to * expose any concrete component classes to the client code, even during the * object tree assembly. The downside is that these methods will be empty * for the leaf-level components. */ publicfunctionadd(Component $component): void{ }
/** * You can provide a method that lets the client code figure out whether a * component can bear children. */ publicfunctionisComposite(): bool { returnfalse; }
/** * The base Component may implement some default behavior or leave it to * concrete classes (by declaring the method containing the behavior as * "abstract"). */ abstractpublicfunctionoperation(): string; }
/** * The Leaf class represents the end objects of a composition. A leaf can't have * any children. * * Usually, it's the Leaf objects that do the actual work, whereas Composite * objects only delegate to their sub-components. */ classLeafextendsComponent { publicfunctionoperation(): string { return"Leaf"; } }
/** * The Composite class represents the complex components that may have children. * Usually, the Composite objects delegate the actual work to their children and * then "sum-up" the result. */ classCompositeextendsComponent { /** * @var \SplObjectStorage */ protected$children;
/** * A composite object can add or remove other components (both simple or * complex) to or from its child list. */ publicfunctionadd(Component $component): void { $this->children->attach($component); $component->setParent($this); }
/** * The Composite executes its primary logic in a particular way. It * traverses recursively through all its children, collecting and summing * their results. Since the composite's children pass these calls to their * children and so forth, the whole object tree is traversed as a result. */ publicfunctionoperation(): string { $results = []; foreach ($this->children as$child) { $results[] = $child->operation(); }
/** * The client code works with all of the components via the base interface. */ functionclientCode(Component $component) { // ...
echo"RESULT: " . $component->operation();
// ... }
/** * This way the client code can support the simple leaf components... */ $simple = newLeaf(); echo"Client: I've got a simple component:\n"; clientCode($simple); echo"\n\n";
/** * ...as well as the complex composites. */ $tree = newComposite(); $branch1 = newComposite(); $branch1->add(newLeaf()); $branch1->add(newLeaf()); $branch2 = newComposite(); $branch2->add(newLeaf()); $tree->add($branch1); $tree->add($branch2); echo"Client: Now I've got a composite tree:\n"; clientCode($tree); echo"\n\n";
/** * Thanks to the fact that the child-management operations are declared in the * base Component class, the client code can work with any component, simple or * complex, without depending on their concrete classes. */ functionclientCode2(Component $component1, Component $component2) { // ...
if ($component1->isComposite()) { $component1->add($component2); } echo"RESULT: " . $component1->operation();
// ... }
echo"Client: I don't need to check the components classes even when managing the tree:\n"; clientCode2($tree, $simple);
Output.txt: 执行结果
1 2 3 4 5 6 7 8
Client: I get a simple component: RESULT: Leaf
Client: Now I get a composite tree: RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf))
Client: I don't need to check the components classes even when managing the tree:: RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf)+Leaf)
真实世界示例
组合模式可以精简任何使用树状递归结构的工作。 HTML DOM 树就是这种结构的例子。 例如, 各种输入元素可担当叶节点, 而表单和字段集则可担当组合的角色。
请记住, 你可以用组合模式以对待树结构内部元素的方式来在整个 HTML 树上执行各种行为, 而又无需让代码与 DOM 树的具体类相耦合。 此类行为的示例可以是渲染 DOM 元素、 将其导出为多种格式、 校验其组件等等。
/** * The base Component class declares an interface for all concrete components, * both simple and complex. * * In our example, we'll be focusing on the rendering behavior of DOM elements. */ abstractclassFormElement { /** * We can anticipate that all DOM elements require these 3 fields. */ protected$name; protected$title; protected$data;
/** * Each concrete DOM element must provide its rendering implementation, but * we can safely assume that all of them are returning strings. */ abstractpublicfunctionrender(): string; }
/** * This is a Leaf component. Like all the Leaves, it can't have any children. */ classInputextendsFormElement { private$type;
/** * Since Leaf components don't have any children that may handle the bulk of * the work for them, usually it is the Leaves who do the most of the heavy- * lifting within the Composite pattern. */ publicfunctionrender(): string { return"<label for=\"{$this->name}\">{$this->title}</label>\n" . "<input name=\"{$this->name}\" type=\"{$this->type}\" value=\"{$this->data}\">\n"; } }
/** * The base Composite class implements the infrastructure for managing child * objects, reused by all Concrete Composites. */ abstractclassFieldCompositeextendsFormElement { /** * @var FormElement[] */ protected$fields = [];
/** * The methods for adding/removing sub-objects. */ publicfunctionadd(FormElement $field): void { $name = $field->getName(); $this->fields[$name] = $field; }
publicfunctionremove(FormElement $component): void { $this->fields = array_filter($this->fields, function ($child) use ($component) { return $child != $component; }); }
/** * Whereas a Leaf's method just does the job, the Composite's method almost * always has to take its sub-objects into account. * * In this case, the composite can accept structured data. * * @param array $data */ publicfunctionsetData($data): void { foreach ($this->fields as$name => $field) { if (isset($data[$name])) { $field->setData($data[$name]); } } }
/** * The same logic applies to the getter. It returns the structured data of * the composite itself (if any) and all the children data. */ publicfunctiongetData(): array { $data = []; foreach ($this->fields as$name => $field) { $data[$name] = $field->getData(); } return$data; }
/** * The base implementation of the Composite's rendering simply combines * results of all children. Concrete Composites will be able to reuse this * implementation in their real rendering implementations. */ publicfunctionrender(): string { $output = ""; foreach ($this->fields as$name => $field) { $output .= $field->render(); } return$output; } }
/** * The fieldset element is a Concrete Composite. */ classFieldsetextendsFieldComposite { publicfunctionrender(): string { // Note how the combined rendering result of children is incorporated // into the fieldset tag. $output = parent::render(); return"<fieldset><legend>{$this->title}</legend>\n$output</fieldset>\n"; } }
/** * And so is the form element. */ classFormextendsFieldComposite { protected$url;
/** * The form structure can be filled with data from various sources. The Client * doesn't have to traverse through all form fields to assign data to various * fields since the form itself can handle that. */ functionloadProductData(FormElement $form) { $data = [ 'name' => 'Apple MacBook', 'description' => 'A decent laptop.', 'photo' => [ 'caption' => 'Front photo.', 'image' => 'photo1.png', ], ];
$form->setData($data); }
/** * The client code can work with form elements using the abstract interface. * This way, it doesn't matter whether the client works with a simple component * or a complex composite tree. */ functionrenderProduct(FormElement $form) { // ..
@parent.setter defparent(self, parent: Component): """ Optionally, the base Component can declare an interface for setting and accessing a parent of the component in a tree structure. It can also provide some default implementation for these methods. """
self._parent = parent
""" In some cases, it would be beneficial to define the child-management operations right in the base Component class. This way, you won't need to expose any concrete component classes to the client code, even during the object tree assembly. The downside is that these methods will be empty for the leaf-level components. """
defis_composite(self) -> bool: """ You can provide a method that lets the client code figure out whether a component can bear children. """
returnFalse
@abstractmethod defoperation(self) -> str: """ The base Component may implement some default behavior or leave it to concrete classes (by declaring the method containing the behavior as "abstract"). """
pass
classLeaf(Component): """ The Leaf class represents the end objects of a composition. A leaf can't have any children. Usually, it's the Leaf objects that do the actual work, whereas Composite objects only delegate to their sub-components. """
defoperation(self) -> str: return"Leaf"
classComposite(Component): """ The Composite class represents the complex components that may have children. Usually, the Composite objects delegate the actual work to their children and then "sum-up" the result. """
defoperation(self) -> str: """ The Composite executes its primary logic in a particular way. It traverses recursively through all its children, collecting and summing their results. Since the composite's children pass these calls to their children and so forth, the whole object tree is traversed as a result. """
results = [] for child in self._children: results.append(child.operation()) returnf"Branch({'+'.join(results)})"
defclient_code(component: Component) -> None: """ The client code works with all of the components via the base interface. """
print(f"RESULT: {component.operation()}", end="")
defclient_code2(component1: Component, component2: Component) -> None: """ Thanks to the fact that the child-management operations are declared in the base Component class, the client code can work with any component, simple or complex, without depending on their concrete classes. """
if component1.is_composite(): component1.add(component2)
if __name__ == "__main__": # This way the client code can support the simple leaf components... simple = Leaf() print("Client: I've got a simple component:") client_code(simple) print("\n")
# ...as well as the complex composites. tree = Composite()
# The base Component class declares common operations for both simple and # complex objects of a composition. classComponent # @return [Component] defparent @parent end
# Optionally, the base Component can declare an interface for setting and # accessing a parent of the component in a tree structure. It can also provide # some default implementation for these methods. defparent=(parent) @parent = parent end
# In some cases, it would be beneficial to define the child-management # operations right in the base Component class. This way, you won't need to # expose any concrete component classes to the client code, even during the # object tree assembly. The downside is that these methods will be empty for # the leaf-level components. defadd(component) raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'" end
# @abstract # # @param [Component] component defremove(component) raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'" end
# You can provide a method that lets the client code figure out whether a # component can bear children. defcomposite? false end
# The base Component may implement some default behavior or leave it to # concrete classes (by declaring the method containing the behavior as # "abstract"). defoperation raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'" end end
# The Leaf class represents the end objects of a composition. A leaf can't have # any children. # # Usually, it's the Leaf objects that do the actual work, whereas Composite # objects only delegate to their sub-components. classLeaf < Component # return [String] defoperation 'Leaf' end end
# The Composite class represents the complex components that may have children. # Usually, the Composite objects delegate the actual work to their children and # then "sum-up" the result. classComposite < Component definitialize @children = [] end
# A composite object can add or remove other components (both simple or # complex) to or from its child list.
# @param [Component] component defadd(component) @children.append(component) component.parent = self end
# @param [Component] component defremove(component) @children.remove(component) component.parent = nil end
# @return [Boolean] defcomposite? true end
# The Composite executes its primary logic in a particular way. It traverses # recursively through all its children, collecting and summing their results. # Since the composite's children pass these calls to their children and so # forth, the whole object tree is traversed as a result. defoperation results = [] @children.each { |child| results.append(child.operation) } "Branch(#{results.join('+')})" end end
# The client code works with all of the components via the base interface. defclient_code(component) puts "RESULT: #{component.operation}" end
# Thanks to the fact that the child-management operations are declared in the # base Component class, the client code can work with any component, simple or # complex, without depending on their concrete classes. defclient_code2(component1, component2) component1.add(component2) if component1.composite?
print "RESULT: #{component1.operation}" end
# This way the client code can support the simple leaf components... simple = Leaf.new puts 'Client: I\'ve got a simple component:' client_code(simple) puts "\n"
# ...as well as the complex composites. tree = Composite.new
/// The base Component class declares common operations for both simple and /// complex objects of a composition. protocolComponent {
/// The base Component may optionally declare methods for setting and /// accessing a parent of the component in a tree structure. It can also /// provide some default implementation for these methods. var parent: Component? { getset }
/// In some cases, it would be beneficial to define the child-management /// operations right in the base Component class. This way, you won't need /// to expose any concrete component classes to the client code, even during /// the object tree assembly. The downside is that these methods will be /// empty for the leaf-level components. funcadd(component: Component) funcremove(component: Component)
/// You can provide a method that lets the client code figure out whether a /// component can bear children. funcisComposite() -> Bool
/// The base Component may implement some default behavior or leave it to /// concrete classes. funcoperation() -> String }
/// The Leaf class represents the end objects of a composition. A leaf can't /// have any children. /// /// Usually, it's the Leaf objects that do the actual work, whereas Composite /// objects only delegate to their sub-components. classLeaf: Component {
var parent: Component?
funcoperation() -> String { return"Leaf" } }
/// The Composite class represents the complex components that may have /// children. Usually, the Composite objects delegate the actual work to their /// children and then "sum-up" the result. classComposite: Component {
var parent: Component?
/// This fields contains the conponent subtree. privatevar children = [Component]()
/// A composite object can add or remove other components (both simple or /// complex) to or from its child list. funcadd(component: Component) { var item = component item.parent =self children.append(item) }
funcremove(component: Component) { // ... }
funcisComposite() -> Bool { returntrue }
/// The Composite executes its primary logic in a particular way. It /// traverses recursively through all its children, collecting and summing /// their results. Since the composite's children pass these calls to their /// children and so forth, the whole object tree is traversed as a result. funcoperation() -> String { let result = children.map({ $0.operation() }) return"Branch("+ result.joined(separator: " ") +")" } }
classClient {
/// The client code works with all of the components via the base interface. staticfuncsomeClientCode(component: Component) { print("Result: "+ component.operation()) }
/// Thanks to the fact that the child-management operations are also /// declared in the base Component class, the client code can work with both /// simple or complex components. staticfuncmoreComplexClientCode(leftComponent: Component, rightComponent: Component) { if leftComponent.isComposite() { leftComponent.add(component: rightComponent) } print("Result: "+ leftComponent.operation()) } }
/// Let's see how it all comes together. classCompositeConceptual: XCTestCase {
functestCompositeConceptual() {
/// This way the client code can support the simple leaf components... print("Client: I've got a simple component:") Client.someClientCode(component: Leaf())
/// ...as well as the complex composites. let tree =Composite()
let branch1 =Composite() branch1.add(component: Leaf()) branch1.add(component: Leaf())
let branch2 =Composite() branch2.add(component: Leaf()) branch2.add(component: Leaf())
print("\nClient: Now I've got a composite tree:") Client.someClientCode(component: tree)
print("\nClient: I don't need to check the components classes even when managing the tree:") Client.moreComplexClientCode(leftComponent: tree, rightComponent: Leaf()) } }
Output.txt: 执行结果
1 2 3 4 5 6 7 8
Client: I've got a simple component: Result: Leaf
Client: Now I've got a composite tree: Result: Branch(Branch(Leaf Leaf) Branch(Leaf Leaf))
Client: I don't need to check the components classes even when managing the tree: Result: Branch(Branch(Leaf Leaf) Branch(Leaf Leaf) Leaf)
Client: Applying 'default' theme for 'UIButton' UIButton: has applied Default Buttom Theme
Client: Applying 'night' theme for 'UIButton' UIButton: has applied Night Buttom Theme
Client: Let's use View Controller as a composite!
Client: Applying 'night button' theme for 'WelcomeViewController'... ContentView: has applied Night Buttom Theme UILabel: has applied Night Buttom Theme UIButton: has applied Night Buttom Theme
/** * The base Component class declares common operations for both simple and * complex objects of a composition. */ abstractclassComponent { protectedparent: Component;
/** * Optionally, the base Component can declare an interface for setting and * accessing a parent of the component in a tree structure. It can also * provide some default implementation for these methods. */ publicsetParent(parent: Component) { this.parent = parent; }
/** * In some cases, it would be beneficial to define the child-management * operations right in the base Component class. This way, you won't need to * expose any concrete component classes to the client code, even during the * object tree assembly. The downside is that these methods will be empty * for the leaf-level components. */ publicadd(component: Component): void { }
publicremove(component: Component): void { }
/** * You can provide a method that lets the client code figure out whether a * component can bear children. */ publicisComposite(): boolean { returnfalse; }
/** * The base Component may implement some default behavior or leave it to * concrete classes (by declaring the method containing the behavior as * "abstract"). */ publicabstractoperation(): string; }
/** * The Leaf class represents the end objects of a composition. A leaf can't have * any children. * * Usually, it's the Leaf objects that do the actual work, whereas Composite * objects only delegate to their sub-components. */ classLeafextendsComponent { publicoperation(): string { return'Leaf'; } }
/** * The Composite class represents the complex components that may have children. * Usually, the Composite objects delegate the actual work to their children and * then "sum-up" the result. */ classCompositeextendsComponent { protectedchildren: Component[] = [];
/** * A composite object can add or remove other components (both simple or * complex) to or from its child list. */ publicadd(component: Component): void { this.children.push(component); component.setParent(this); }
/** * The Composite executes its primary logic in a particular way. It * traverses recursively through all its children, collecting and summing * their results. Since the composite's children pass these calls to their * children and so forth, the whole object tree is traversed as a result. */ publicoperation(): string { const results = []; for (const child ofthis.children) { results.push(child.operation()); }
return`Branch(${results.join('+')})`; } }
/** * The client code works with all of the components via the base interface. */ functionclientCode(component: Component) { // ...
console.log(`RESULT: ${component.operation()}`);
// ... }
/** * This way the client code can support the simple leaf components... */ const simple = newLeaf(); console.log('Client: I\'ve got a simple component:'); clientCode(simple); console.log('');
/** * ...as well as the complex composites. */ const tree = newComposite(); const branch1 = newComposite(); branch1.add(newLeaf()); branch1.add(newLeaf()); const branch2 = newComposite(); branch2.add(newLeaf()); tree.add(branch1); tree.add(branch2); console.log('Client: Now I\'ve got a composite tree:'); clientCode(tree); console.log('');
/** * Thanks to the fact that the child-management operations are declared in the * base Component class, the client code can work with any component, simple or * complex, without depending on their concrete classes. */ functionclientCode2(component1: Component, component2: Component) { // ...
if (component1.isComposite()) { component1.add(component2); } console.log(`RESULT: ${component1.operation()}`);
// ... }
console.log('Client: I don\'t need to check the components classes even when managing the tree:'); clientCode2(tree, simple);
Output.txt: 执行结果
1 2 3 4 5 6 7 8
Client: I've got a simple component: RESULT: Leaf
Client: Now I've got a composite tree: RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf))
Client: I don't need to check the components classes even when managing the tree: RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf)+Leaf)
Serching recursively for keyword rose in folder Folder2 Searching for keyword rose in file File2 Searching for keyword rose in file File3 Serching recursively for keyword rose in folder Folder1 Searching for keyword rose in file File1