Skip to main content

behavioral

Behavioral design patterns from the Gang of Four — Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, and Visitor. Patterns that manage algorithms, relationships, and responsibilities between objects. USE FOR: object communication, event handling, state management, algorithm encapsulation, request handling chains, undo/redo, publish-subscribe DO NOT USE FOR: object creation (use creational), structural composition (use structural)

소스 정보

저장소
Tyler-R-Kendrick/agent-skills
최근 소스 활동
2026년 2월 11일 05:14
감지된 SKILL.md 언어
영어
스타
11
포크
4

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
4 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
behavioral
description
Behavioral design patterns from the Gang of Four — Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, and Visitor. Patterns that manage algorithms, relationships, and responsibilities between objects. USE FOR: object communication, event handling, state management, algorithm encapsulation, request handling chains, undo/redo, publish-subscribe DO NOT USE FOR: object creation (use creational), structural composition (use structural)
license
MIT
metadata
{"displayName":"Behavioral Patterns","author":"Tyler-R-Kendrick"}
compatibility
claude, copilot, cursor
references
[{"title":"Refactoring.Guru — Behavioral Design Patterns","url":"https://refactoring.guru/design-patterns/behavioral-patterns"},{"title":"Behavioral Pattern — Wikipedia","url":"https://en.wikipedia.org/wiki/Behavioral_pattern"}]
# Behavioral Design Patterns ## Overview Behavioral patterns are concerned with algorithms and the assignment of responsibilities between objects. They describe not just patterns of objects or classes but also the patterns of communication between them. These patterns characterize complex control flow that is difficult to follow at run-time — they shift your focus away from flow of control to the way objects are interconnected. --- ## 1. Chain of Responsibility ### Intent Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it. ### Structure ``` ┌──────────────────┐ │ Handler │◀────────────┐ │ (interface) │ │ next ├──────────────────┤ │ │ + handle(req) │─────────────┘ │ + setNext(h) │ └──────┬───────────┘ │ implements ├──────────────┬──────────────┐ ▼ ▼ ▼ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ HandlerA │ │ HandlerB │ │ HandlerC │ └────────────┘ └────────────┘ └────────────┘ ``` ### Participants - **Handler** — defines an interface for handling requests; optionally links to a successor - **ConcreteHandler** — handles requests it is responsible for; forwards unhandled requests to the next handler - **Client** — initiates the request to a handler in the chain ### When to Use - More than one object may handle a request, and the handler is not known a priori - You want to issue a request to one of several objects without specifying the receiver explicitly - The set of handlers should be configurable dynamically (e.g., middleware pipelines) ### TypeScript Example ```typescript // Handler interface interface SupportHandler { setNext(handler: SupportHandler): SupportHandler; handle(issue: { level: string; message: string }): string; } // Base handler abstract class BaseSupportHandler implements SupportHandler { private next: SupportHandler | null = null; setNext(handler: SupportHandler): SupportHandler { this.next = handler; return handler; } handle(issue: { level: string; message: string }): string { if (this.next) { return this.next.handle(issue); } return `No handler found for: ${issue.message}`; } } // Concrete handlers class TierOneSupport extends BaseSupportHandler { handle(issue: { level: string; message: string }): string { if (issue.level === "basic") { return `[Tier 1] Resolved: ${issue.message}`; } return super.handle(issue); } } class TierTwoSupport extends BaseSupportHandler { handle(issue: { level: string; message: string }): string { if (issue.level === "intermediate") { return `[Tier 2] Resolved: ${issue.message}`; } return super.handle(issue); } } class EngineeringSupport extends BaseSupportHandler { handle(issue: { level: string; message: string }): string { if (issue.level === "critical") { return `[Engineering] Resolved: ${issue.message}`; } return super.handle(issue); } } // Usage — build the chain const tier1 = new TierOneSupport(); const tier2 = new TierTwoSupport(); const engineering = new EngineeringSupport(); tier1.setNext(tier2).setNext(engineering); console.log(tier1.handle({ level: "basic", message: "Password reset" })); // [Tier 1] Resolved: Password reset console.log(tier1.handle({ level: "critical", message: "Data corruption" })); // [Engineering] Resolved: Data corruption ``` --- ## 2. Command ### Intent Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations. ### Structure ``` ┌──────────┐ ┌──────────────────┐ ┌──────────────┐ │ Invoker │──────▶│ Command │ │ Receiver │ │ │ │ (interface) │ ├──────────────┤ └──────────┘ ├──────────────────┤ │ + action() │ │ + execute() │ └──────┬───────┘ │ + undo() │ │ └──────┬───────────┘ │ │ implements │ ▼ │ ┌──────────────────┐ │ │ ConcreteCommand │──────────────┘ ├──────────────────┤ calls │ - receiver │ │ - state │ │ + execute() │ │ + undo() │ └──────────────────┘ ``` ### Participants - **Command** — declares an interface for executing an operation - **ConcreteCommand** — binds a Receiver to an action; implements execute/undo - **Invoker** — asks the command to carry out the request - **Receiver** — knows how to perform the operations associated with the request ### When to Use - You need to parameterize objects with an action to perform - You need to specify, queue, and execute requests at different times - You need to support undo/redo - You need to support logging changes so they can be reapplied after a crash ### TypeScript Example ```typescript // Receiver class TextEditor { content = ""; insert(text: string, position: number): void { this.content = this.content.slice(0, position) + text + this.content.slice(position); } delete(position: number, length: number): string { const deleted = this.content.slice(position, position + length); this.content = this.content.slice(0, position) + this.content.slice(position + length); return deleted; } } // Command interface interface EditorCommand { execute(): void; undo(): void; } // Concrete commands class InsertCommand implements EditorCommand { constructor( private editor: TextEditor, private text: string, private position: number ) {} execute(): void { this.editor.insert(this.text, this.position); } undo(): void { this.editor.delete(this.position, this.text.length); } } class DeleteCommand implements EditorCommand { private deletedText = ""; constructor( private editor: TextEditor, private position: number, private length: number ) {} execute(): void { this.deletedText = this.editor.delete(this.position, this.length); } undo(): void { this.editor.insert(this.deletedText, this.position); } } // Invoker with undo/redo class CommandHistory { private undoStack: EditorCommand[] = []; private redoStack: EditorCommand[] = []; execute(command: EditorCommand): void { command.execute(); this.undoStack.push(command); this.redoStack = []; // clear redo on new action } undo(): void { const cmd = this.undoStack.pop(); if (cmd) { cmd.undo(); this.redoStack.push(cmd); } } redo(): void { const cmd = this.redoStack.pop(); if (cmd) { cmd.execute(); this.undoStack.push(cmd); } } } // Usage const editor = new TextEditor(); const history = new CommandHistory(); history.execute(new InsertCommand(editor, "Hello", 0)); history.execute(new InsertCommand(editor, " World", 5)); console.log(editor.content); // "Hello World" history.undo(); console.log(editor.content); // "Hello" history.redo(); console.log(editor.content); // "Hello World" ``` --- ## 3. Iterator ### Intent Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation. ### Structure ``` ┌──────────────────┐ ┌──────────────────┐ │ Aggregate │───────▶│ Iterator │ │ (interface) │creates │ (interface) │ ├──────────────────┤ ├──────────────────┤ │ + createIterator()│ │ + hasNext(): bool │ └──────────────────┘ │ + next(): T │ └──────────────────┘ ``` ### Participants - **Iterator** — defines an interface for accessing and traversing elements - **ConcreteIterator** — implements the Iterator interface; tracks the current position - **Aggregate** — defines an interface for creating an Iterator object - **ConcreteAggregate** — returns an instance of the ConcreteIterator ### When to Use - You want to access a collection's elements without exposing its internal structure - You want to support multiple traversals of the same collection - You want a uniform interface for traversing different types of collections ### TypeScript Example ```typescript // Iterator interface interface Iterator<T> { hasNext(): boolean; next(): T; reset(): void; } // Concrete collection with custom iterator class TreeNode<T> { children: TreeNode<T>[] = []; constructor(public value: T) {} add(...nodes: TreeNode<T>[]): this { this.children.push(...nodes); return this; } } // Depth-first iterator class DepthFirstIterator<T> implements Iterator<T> { private stack: TreeNode<T>[]; constructor(private root: TreeNode<T>) { this.stack = [root]; } hasNext(): boolean { return this.stack.length > 0; } next(): T { if (!this.hasNext()) throw new Error("No more elements"); const node = this.stack.pop()!; // Push children in reverse so left child is processed first for (let i = node.children.length - 1; i >= 0; i--) { this.stack.push(node.children[i]); } return node.value; } reset(): void { this.stack = [this.root]; } } // Breadth-first iterator class BreadthFirstIterator<T> implements Iterator<T> { private queue: TreeNode<T>[]; constructor(private root: TreeNode<T>) { this.queue = [root]; } hasNext(): boolean { return this.queue.length > 0; } next(): T { if (!this.hasNext()) throw new Error("No more elements"); const node = this.queue.shift()!; this.queue.push(...node.children); return node.value; } reset(): void { this.queue = [this.root]; } } // Usage const tree = new TreeNode("A") .add( new TreeNode("B").add(new TreeNode("D"), new TreeNode("E")), new TreeNode("C").add(new TreeNode("F")) ); const dfs = new DepthFirstIterator(tree); const dfsResult: string[] = []; while (dfs.hasNext()) dfsResult.push(dfs.next()); console.log("DFS:", dfsResult.join(" -> ")); // A -> B -> D -> E -> C -> F const bfs = new BreadthFirstIterator(tree); const bfsResult: string[] = []; while (bfs.hasNext()) bfsResult.push(bfs.next()); console.log("BFS:", bfsResult.join(" -> ")); // A -> B -> C -> D -> E -> F ``` --- ## 4. Mediator ### Intent Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently. ### Structure ``` ┌──────────────────┐ ┌──────────────────┐ │ Mediator │◀───────│ Colleague │ │ (interface) │ │ (interface) │ ├──────────────────┤ ├──────────────────┤ │ + notify(sender, │ │ - mediator │ │ event) │ └──────┬───────────┘ └──────┬───────────┘ │ implements │ implements ├──────────┐ ▼ ▼ ▼ ┌──────────────────┐ ┌──────────┐┌──────────┐ │ ConcreteMediator │ │ColleagueA││ColleagueB│ │ │ └──────────┘└──────────┘ │ - colleagueA │ │ - colleagueB │ └──────────────────┘ ``` ### Participants - **Mediator** — defines an interface for communicating with Colleague objects - **ConcreteMediator** — implements cooperative behavior by coordinating Colleague objects - **Colleague** — each Colleague knows its Mediator and communicates with it instead of other Colleagues ### When to Use - A set of objects communicate in well-defined but complex ways - Reusing an object is difficult because it refers to and communicates with many other objects - A behavior distributed between several classes should be customizable without subclassing ### TypeScript Example ```typescript // Mediator interface interface ChatMediator { sendMessage(message: string, sender: ChatUser): void; addUser(user: ChatUser): void; } // Colleague class ChatUser { private messages: string[] = []; constructor( public name: string, private mediator: ChatMediator ) { mediator.addUser(this); } send(message: string): void { console.log(`${this.name} sends: ${message}`); this.mediator.sendMessage(message, this); } receive(message: string, from: string): void { const formatted = `${from}: ${message}`; this.messages.push(formatted); console.log(` ${this.name} received <- ${formatted}`); } getHistory(): string[] { return [...this.messages]; } } // Concrete mediator class ChatRoom implements ChatMediator { private users: ChatUser[] = []; addUser(user: ChatUser): void { this.users.push(user); } sendMessage(message: string, sender: ChatUser): void { for (const user of this.users) { if (user !== sender) { user.receive(message, sender.name); } } } } // Usage — users never reference each other directly const room = new ChatRoom(); const alice = new ChatUser("Alice", room); const bob = new ChatUser("Bob", room); const charlie = new ChatUser("Charlie", room); alice.send("Hello everyone!"); // Alice sends: Hello everyone! // Bob received <- Alice: Hello everyone! // Charlie received <- Alice: Hello everyone! bob.send("Hey Alice!"); // Bob sends: Hey Alice! // Alice received <- Bob: Hey Alice! // Charlie received <- Bob: Hey Alice! ``` --- ## 5. Memento ### Intent Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later. ### Structure ``` ┌──────────────┐ ┌──────────────────┐ ┌──────────────┐ │ Caretaker │────▶│ Memento │◀────│ Originator │ ├──────────────┤keeps│ (opaque) │saves├──────────────┤ │ - mementos[] │ ├──────────────────┤ │ - state │ └──────────────┘ │ + getState() │ │ + save() │ └──────────────────┘ │ + restore(m) │ └──────────────┘ ```
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기