From harness-claude
Implements the GoF Composite pattern to compose objects into tree structures and treat individual and composite objects uniformly. Useful for file systems, menus, ASTs, and recursive permissions.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:gof-composite-patternThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Compose objects into tree structures and treat individual and composite objects uniformly.
Compose objects into tree structures and treat individual and composite objects uniformly.
Core structure — Component interface, Leaf, Composite:
// Component — uniform interface for both leaves and composites
interface FileSystemItem {
name: string;
size(): number;
print(indent?: string): void;
}
// Leaf — no children
class File implements FileSystemItem {
constructor(
public readonly name: string,
private readonly bytes: number
) {}
size(): number {
return this.bytes;
}
print(indent = ''): void {
console.log(`${indent}📄 ${this.name} (${this.bytes}B)`);
}
}
// Composite — has children, delegates to them
class Directory implements FileSystemItem {
private children: FileSystemItem[] = [];
constructor(public readonly name: string) {}
add(item: FileSystemItem): this {
this.children.push(item);
return this;
}
remove(item: FileSystemItem): void {
this.children = this.children.filter((c) => c !== item);
}
size(): number {
// Recursion handled uniformly — leaves and composites both have size()
return this.children.reduce((total, child) => total + child.size(), 0);
}
print(indent = ''): void {
console.log(`${indent}📁 ${this.name}`);
for (const child of this.children) {
child.print(indent + ' ');
}
}
}
// Client code treats everything as FileSystemItem
function printSummary(item: FileSystemItem): void {
item.print();
console.log(`Total size: ${item.size()}B`);
}
// Build the tree
const root = new Directory('project')
.add(new File('package.json', 512))
.add(new File('tsconfig.json', 256))
.add(
new Directory('src')
.add(new File('index.ts', 1024))
.add(new Directory('utils').add(new File('logger.ts', 768)))
);
printSummary(root);
Permission tree (practical RBAC example):
interface Permission {
name: string;
check(userId: string, action: string): boolean;
}
class AtomicPermission implements Permission {
constructor(
public readonly name: string,
private readonly resource: string
) {}
check(userId: string, action: string): boolean {
// Real implementation would check DB
return action === this.resource;
}
}
class PermissionGroup implements Permission {
private permissions: Permission[] = [];
constructor(public readonly name: string) {}
add(permission: Permission): this {
this.permissions.push(permission);
return this;
}
// OR semantics: granted if any child grants it
check(userId: string, action: string): boolean {
return this.permissions.some((p) => p.check(userId, action));
}
}
const adminRole = new PermissionGroup('admin')
.add(new AtomicPermission('read-users', 'users'))
.add(new AtomicPermission('write-users', 'users'))
.add(
new PermissionGroup('billing')
.add(new AtomicPermission('read-invoices', 'invoices'))
.add(new AtomicPermission('write-invoices', 'invoices'))
);
TypeScript discriminated union alternative: For simpler cases, a discriminated union often beats a class hierarchy:
type TreeNode =
| { kind: 'leaf'; name: string; value: number }
| { kind: 'branch'; name: string; children: TreeNode[] };
function sum(node: TreeNode): number {
if (node.kind === 'leaf') return node.value;
return node.children.reduce((acc, child) => acc + sum(child), 0);
}
Anti-patterns:
add/remove on the Component interface — leaves can't implement these; use optional methods or a type guardadd()Traversal strategies:
function* depthFirst(item: FileSystemItem): Generator<FileSystemItem> {
yield item;
if (item instanceof Directory) {
for (const child of item.getChildren()) {
yield* depthFirst(child);
}
}
}
// Count all files
const fileCount = [...depthFirst(root)].filter((item) => item instanceof File).length;
refactoring.guru/design-patterns/composite
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeImplements the Composite design pattern to compose objects into tree structures, allowing uniform treatment of leaves and composites. Useful for file systems, UI trees, menus.
Applies the Composite design pattern to compose objects into tree structures, enabling uniform treatment of leaf and container nodes for part-whole hierarchies.
Generates Composite pattern for PHP 8.4 with interface, leaf, composite classes, and unit tests. For tree structures like menus, file systems, org charts.