デコレータ
既存の関数やクラスに機能を追加するデザインパターンで、元のコードを変更せずに拡張する
設計パターンTypeScript
デコレータとは
デコレータ (Decorator) は、既存の関数やクラスに機能を追加するデザインパターンで、元のコードを変更せずに拡張する。GoF デザインパターンの 1 つで、Python の @decorator、TypeScript の Stage 3 Decorators が言語レベルでサポートする。
関数デコレータ (高階関数)
// ログを追加するデコレータ
function withLogging<T extends (...args: any[]) => any>(fn: T): T {
return ((...args: any[]) => {
console.log(`Calling ${fn.name} with`, args);
const result = fn(...args);
console.log(`Result:`, result);
return result;
}) as T;
}
const add = (a: number, b: number) => a + b;
const loggedAdd = withLogging(add);
loggedAdd(1, 2); // Calling add with [1, 2] → Result: 3
TypeScript Decorators (Stage 3)
function log(target: any, context: ClassMethodDecoratorContext) {
return function (...args: any[]) {
console.log(`${String(context.name)} called`);
return target.apply(this, args);
};
}
class OrderService {
@log
createOrder(data: any) { /* ... */ }
}
デコレータ vs 継承
| 観点 | デコレータ | 継承 |
|---|---|---|
| 結合度 | 低い | 高い |
| 組み合わせ | 自由に組み合わせ可能 | 単一継承の制約 |
| 実行時の変更 | 可能 | 不可 |
Python のデコレータ
import functools
def retry(max_attempts=3):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for i in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception:
if i == max_attempts - 1:
raise
return wrapper
return decorator
@retry(max_attempts=3)
def call_api():
...
実用的なデコレータ
| デコレータ | 用途 |
|---|---|
| withLogging | ログの追加 |
| withRetry | リトライの追加 |
| withCache | キャッシュの追加 |
| withAuth | 認証チェック |
| withValidation | 入力検証 |
詳しくは関連書籍を参照。