/** * Composite Pattern 组合是一种结构型设计模式, 你可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们。 * https://refactoringguru.cn/design-patterns/composite/typescript/example#lang-features * The base Component class declares common operations for both simple and * complex objects of a composition. * * */ abstract class DuComponent { protected parent!: DuComponent | null; /** * 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 setParent(parent: DuComponent | null) { this.parent = parent; } /** * */ public getParent(): DuComponent | null { return this.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. */ public add(component: DuComponent): void { } /** * * @param component */ public remove(component: DuComponent): void { } /** * You can provide a method that lets the client code figure out whether a * component can bear children. */ public isComposite(): boolean { return false; } /** * The base Component may implement some default behavior or leave it to * concrete classes (by declaring the method containing the behavior as * "abstract"). */ public abstract operation(): 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. */ class Leaf extends DuComponent { public operation(): 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. */ class Composite extends DuComponent { protected children: DuComponent[] = []; /** * A composite object can add or remove other components (both simple or * complex) to or from its child list. */ public add(component: DuComponent): void { this.children.push(component); component.setParent(this); } /** * * @param component */ public remove(component: DuComponent): void { const componentIndex = this.children.indexOf(component); this.children.splice(componentIndex, 1); component.setParent(null); } /** * */ public isComposite(): boolean { return true; } /** * 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. */ public operation(): string { const results = []; for (const child of this.children) { results.push(child.operation()); } return `Branch(${results.join('+')})`; } } /** * The client code works with all of the components via the base interface. */ function clientCodeCompostite(component: DuComponent) { // ... let str=""; console.log(`RESULT: ${component.operation()}`); str=str+component.operation(); return str; // ... } /** * This way the client code can support the simple leaf components... */ let strCom=""; const simple = new Leaf(); console.log('Client: I\'ve got a simple component:'); strCom=clientCodeCompostite(simple); console.log(''); /** * ...as well as the complex composites. */ const tree = new Composite(); const branch1 = new Composite(); branch1.add(new Leaf()); branch1.add(new Leaf()); const branch2 = new Composite(); branch2.add(new Leaf()); tree.add(branch1); tree.add(branch2); console.log('Client: Now I\'ve got a composite tree:'); let strCom1=clientCodeCompostite(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. */ function clientCodeCompostite2(component1: DuComponent, component2: DuComponent) { // ... let str=""; if (component1.isComposite()) { component1.add(component2); } console.log(`RESULT: ${component1.operation()}`); return str=component1.operation()+","+component2.operation(); } console.log('Client: I don\'t need to check the components classes even when managing the tree:'); let strCom2=clientCodeCompostite2(tree, simple); let messageComposite: string = 'Hello World,This is a typescript!,涂聚文 Geovin Du Web'; document.body.innerHTML = messageComposite+",one="+strCom+",two="+strCom1+",three="+strCom2+",TypeScript 组合模式"
调用:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <head><title>TypeScript:桥接模式</title> <meta name="Description" content="geovindu,涂聚文,Geovin Du"/> <meta name="Keywords" content="geovindu,涂聚文,Geovin Du"/> <meta name="author" content="geovindu,涂聚文,Geovin Du"/> </head> <body> <script src="dist/Compositets.js"></script> </body> </html>
输出: