热门角色不仅是灵感来源,更是你的效率助手。通过精挑细选的角色提示词,你可以快速生成高质量内容、提升创作灵感,并找到最契合你需求的解决方案。让创作更轻松,让价值更直接!
我们根据不同用户需求,持续更新角色库,让你总能找到合适的灵感入口。
为指定的设计模式提供详细解析,覆盖结构、关键角色、使用场景与优缺点,并结合具体编程语言附上清晰代码示例,帮助开发者快速理解并应用设计模式。
以下从软件设计角度和 Go 语言的实现习惯,系统讲解策略模式(Strategy Pattern),并给出一个中等复杂度的示例。
一、作用
二、结构(关键组件与角色)
三、常见使用场景
四、优缺点
五、Go 语言实现示例(重试与回退策略) 说明:
代码:
package main
import (
"context"
"fmt"
"math"
"math/rand"
"time"
)
// Strategy:回退策略接口
type BackoffStrategy interface {
NextDelay(attempt int, err error) time.Duration
}
// ConcreteStrategy:固定间隔回退
type ConstantBackoff struct {
Interval time.Duration
}
func (c ConstantBackoff) NextDelay(attempt int, err error) time.Duration {
return c.Interval
}
// ConcreteStrategy:指数回退(带最大值与抖动)
type ExponentialBackoff struct {
Base time.Duration // 初始基准延迟
Factor float64 // 每次递增的倍率
Max time.Duration // 最大延迟
Jitter float64 // 抖动比例,范围 [0,1] 较为合理,表示±百分比
}
func (e ExponentialBackoff) NextDelay(attempt int, err error) time.Duration {
if attempt < 1 {
attempt = 1
}
delay := float64(e.Base) * math.Pow(e.Factor, float64(attempt-1))
if e.Max > 0 && time.Duration(delay) > e.Max {
delay = float64(e.Max)
}
// 应用抖动:在 [1-Jitter, 1+Jitter] 区间随机缩放
if e.Jitter > 0 {
min := 1 - e.Jitter
max := 1 + e.Jitter
noise := min + rand.Float64()*(max-min)
delay *= noise
}
if delay < 0 {
delay = 0
}
return time.Duration(delay)
}
// 可选:用于判断是否应该重试的谓词策略
type RetryPredicate func(error) bool
// 一个用于示例的临时错误接口
type TemporaryError interface {
error
Temporary() bool
}
type transientError struct{ msg string }
func (e transientError) Error() string { return e.msg }
func (e transientError) Temporary() bool { return true }
// Context:重试器,封装重试流程并使用 BackoffStrategy
type Retrier struct {
MaxAttempts int
Backoff BackoffStrategy
ShouldRetry RetryPredicate // 可选,不设置则全部重试
}
func NewRetrier(max int, backoff BackoffStrategy, pred RetryPredicate) *Retrier {
return &Retrier{
MaxAttempts: max,
Backoff: backoff,
ShouldRetry: pred,
}
}
func (r *Retrier) Do(ctx context.Context, op func(context.Context) error) error {
if r.MaxAttempts < 1 {
return fmt.Errorf("MaxAttempts must be >= 1")
}
var lastErr error
for attempt := 1; attempt <= r.MaxAttempts; attempt++ {
err := op(ctx)
if err == nil {
return nil
}
lastErr = err
if r.ShouldRetry != nil && !r.ShouldRetry(err) {
return err
}
if attempt == r.MaxAttempts {
break
}
delay := r.Backoff.NextDelay(attempt, err)
fmt.Printf("attempt=%d failed: %v; backing off for %v\n", attempt, err, delay)
// 尊重上下文取消或超时
select {
case <-time.After(delay):
case <-ctx.Done():
return ctx.Err()
}
}
return lastErr
}
// 一个不稳定的服务,用于演示
type flakyService struct {
failUntil int // 前 failUntil 次调用都会失败
calls int
}
func (s *flakyService) call(ctx context.Context) error {
s.calls++
fmt.Printf("calling service (attempt %d)\n", s.calls)
if s.calls <= s.failUntil {
return transientError{msg: "network glitch"}
}
// 模拟成功
fmt.Println("service succeeded")
return nil
}
func main() {
rand.Seed(time.Now().UnixNano())
// 上下文设置 5 秒超时
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
svc := &flakyService{failUntil: 3}
// 使用指数回退策略(带抖动)
exp := ExponentialBackoff{
Base: 100 * time.Millisecond,
Factor: 2.0,
Max: 1 * time.Second,
Jitter: 0.3, // ±30% 抖动
}
shouldRetry := func(err error) bool {
// 只重试临时错误
if te, ok := err.(TemporaryError); ok && te.Temporary() {
return true
}
return false
}
retrier := NewRetrier(5, exp, shouldRetry)
fmt.Println("== Run with ExponentialBackoff ==")
if err := retrier.Do(ctx, svc.call); err != nil {
fmt.Printf("final error: %v\n", err)
}
// 运行时切换策略:改为固定间隔策略
fmt.Println("\n== Switch to ConstantBackoff ==")
retrier.Backoff = ConstantBackoff{Interval: 200 * time.Millisecond}
svc.failUntil = 5
svc.calls = 0
if err := retrier.Do(ctx, svc.call); err != nil {
fmt.Printf("final error: %v\n", err)
}
}
要点解析(结合示例)
实践建议(Go 习惯)
通过上述结构与示例,你可以把任何可替换的算法封装为策略接口或函数类型,做到在 Go 项目中既优雅又高效地管理行为变体。
以下内容围绕观察者模式在 TypeScript 中的作用、结构、常见使用场景、优缺点,并附上一个简单清晰的代码示例。
作用
结构(关键组件与角色)
两种通知模式(重要变体)
常见使用场景
优点
缺点
TypeScript 简单示例(Push 模式,强类型)
// 定义观察者接口(泛型,强类型)
interface Observer<T> {
update(data: T): void;
}
// 定义主题接口
interface Subject<T> {
attach(observer: Observer<T>): () => void; // 返回取消订阅函数,便于使用
detach(observer: Observer<T>): void;
notify(data: T): void;
}
// 一个具体主题:温度传感器(推送最新温度)
class TemperatureSensor implements Subject<number> {
private observers = new Set<Observer<number>>();
private temperature = 20;
attach(observer: Observer<number>): () => void {
this.observers.add(observer);
// 返回取消订阅函数,避免遗忘 detach
return () => this.detach(observer);
}
detach(observer: Observer<number>): void {
this.observers.delete(observer);
}
setTemperature(value: number): void {
this.temperature = value;
this.notify(this.temperature);
}
notify(data: number): void {
// 复制迭代,避免通知过程中集合被修改影响遍历
for (const obs of [...this.observers]) {
try {
obs.update(data);
} catch (err) {
console.error('Observer failed:', err);
}
}
}
}
// 具体观察者:仪表盘显示
class DashboardDisplay implements Observer<number> {
update(temp: number): void {
console.log(`Dashboard: current temperature is ${temp}°C`);
}
}
// 具体观察者:风扇控制器
class FanController implements Observer<number> {
update(temp: number): void {
const on = temp >= 28;
console.log(on ? 'FanController: Fan ON' : 'FanController: Fan OFF');
}
}
// 使用
const sensor = new TemperatureSensor();
const dashboard = new DashboardDisplay();
const fan = new FanController();
const unsubscribeFan = sensor.attach(fan);
sensor.attach(dashboard);
sensor.setTemperature(26); // 通知:风扇关、仪表盘显示
sensor.setTemperature(31); // 通知:风扇开、仪表盘显示
unsubscribeFan(); // 取消订阅风扇
sensor.setTemperature(25); // 仅仪表盘接收通知
实践建议
下面从架构视角系统讲解装饰器模式在 Python 中的作用、结构、使用场景与优缺点,并附上一个较为复杂但清晰的示例代码。
一、作用
二、结构(关键组件与角色)
三、常见使用场景
四、优缺点
五、代码示例(复杂示例:在数据获取组件上叠加缓存、重试、熔断、度量) 说明:
代码:
import time
import random
from abc import ABC, abstractmethod
from collections import OrderedDict
from typing import Dict, Optional, Tuple, Any
# =========================
# 领域与错误类型
# =========================
class TransientError(Exception):
"""可重试的瞬时错误(例如网络抖动、服务暂不可用)。"""
pass
class NotFoundError(Exception):
"""不可重试的错误(例如资源不存在)。"""
pass
class CircuitOpenError(Exception):
"""熔断器打开,拒绝调用。"""
pass
# =========================
# 组件接口与具体实现
# =========================
class Fetcher(ABC):
"""Component:数据获取接口"""
@abstractmethod
def fetch(self, url: str, headers: Optional[Dict[str, str]] = None) -> str:
pass
class UnstableFetcher(Fetcher):
"""
ConcreteComponent:不稳定的数据源,模拟真实服务的随机失败与延迟。
- failure_rate: 随机失败概率(TransientError)
- latency_range: 延迟范围(秒)
- data: 简单的URL->字符串数据映射
"""
def __init__(self, data: Dict[str, str], failure_rate: float = 0.3, latency_range: Tuple[float, float] = (0.05, 0.2)):
self.data = data
self.failure_rate = failure_rate
self.latency_range = latency_range
def fetch(self, url: str, headers: Optional[Dict[str, str]] = None) -> str:
# 模拟随机延迟
time.sleep(random.uniform(*self.latency_range))
# 模拟不可重试错误:不存在
if url not in self.data:
raise NotFoundError(f"URL not found: {url}")
# 模拟可重试错误:瞬时失败
if random.random() < self.failure_rate:
raise TransientError("Random transient failure.")
return self.data[url]
# =========================
# 抽象装饰器
# =========================
class FetcherDecorator(Fetcher):
"""Decorator:持有被装饰对象,并实现同样的接口"""
def __init__(self, inner: Fetcher):
self._inner = inner
def fetch(self, url: str, headers: Optional[Dict[str, str]] = None) -> str:
return self._inner.fetch(url, headers=headers)
# =========================
# Metrics 度量中心(供多个装饰器共享)
# =========================
class MetricsRegistry:
def __init__(self):
self.counters: Dict[str, int] = {}
self.timers: Dict[str, float] = {}
def inc(self, key: str, n: int = 1):
self.counters[key] = self.counters.get(key, 0) + n
def add_time(self, key: str, ms: float):
self.timers[key] = self.timers.get(key, 0.0) + ms
def snapshot(self) -> Dict[str, Any]:
return {
"counters": dict(self.counters),
"timers_ms": dict(self.timers),
}
# =========================
# ConcreteDecorator:熔断器
# =========================
class CircuitBreakerFetcher(FetcherDecorator):
"""
熔断器状态机:
- closed: 正常。累积失败达到阈值 -> open
- open: 拒绝请求,等待恢复时间 -> half_open
- half_open: 允许一次试探请求;成功 -> closed;失败 -> open
"""
def __init__(self, inner: Fetcher, failure_threshold: int = 3, recovery_time: float = 3.0, metrics: Optional[MetricsRegistry] = None):
super().__init__(inner)
self.failure_threshold = failure_threshold
self.recovery_time = recovery_time
self.metrics = metrics
self._state = "closed"
self._consecutive_failures = 0
self._opened_at = 0.0
self._half_open_trial_in_progress = False
def _to_open(self):
self._state = "open"
self._opened_at = time.time()
self._half_open_trial_in_progress = False
def _maybe_to_half_open(self):
if self._state == "open" and (time.time() - self._opened_at) >= self.recovery_time:
self._state = "half_open"
self._half_open_trial_in_progress = False
def fetch(self, url: str, headers: Optional[Dict[str, str]] = None) -> str:
# open -> half_open if冷却结束
self._maybe_to_half_open()
if self._state == "open":
if self.metrics:
self.metrics.inc("circuit_open_skips")
raise CircuitOpenError("Circuit breaker is OPEN")
if self._state == "half_open":
# 允许一次试探请求
if self._half_open_trial_in_progress:
# 有另一个试探中,拒绝(简单处理并发;单线程可忽略)
raise CircuitOpenError("Half-open trial in progress")
self._half_open_trial_in_progress = True
try:
result = self._inner.fetch(url, headers=headers)
# 成功:重置并转为closed(若half_open)
self._consecutive_failures = 0
if self._state == "half_open":
self._state = "closed"
self._half_open_trial_in_progress = False
return result
except Exception as e:
# 失败:计数并根据阈值转open
self._consecutive_failures += 1
if self._state == "half_open":
# half-open失败立即转open
self._to_open()
elif self._consecutive_failures >= self.failure_threshold:
self._to_open()
raise
# =========================
# ConcreteDecorator:重试(指数退避+抖动)
# =========================
class RetryFetcher(FetcherDecorator):
"""
对指定异常进行重试,支持指数退避与随机抖动。
- retry_exceptions: 需要重试的异常类型集合
- giveup_exceptions: 直接放弃的异常,不重试(如 CircuitOpenError、NotFoundError)
"""
def __init__(self, inner: Fetcher, retries: int = 3, backoff_base: float = 0.1,
retry_exceptions: Tuple[type, ...] = (TransientError,),
giveup_exceptions: Tuple[type, ...] = (CircuitOpenError, NotFoundError),
metrics: Optional[MetricsRegistry] = None):
super().__init__(inner)
self.retries = retries
self.backoff_base = backoff_base
self.retry_exceptions = retry_exceptions
self.giveup_exceptions = giveup_exceptions
self.metrics = metrics
def fetch(self, url: str, headers: Optional[Dict[str, str]] = None) -> str:
attempt = 0
while True:
try:
return self._inner.fetch(url, headers=headers)
except self.giveup_exceptions:
# 直接放弃,不做重试
raise
except self.retry_exceptions as e:
attempt += 1
if self.metrics:
self.metrics.inc("retries_attempted")
if attempt > self.retries:
raise
# 指数退避 + 随机抖动
delay = self.backoff_base * (2 ** (attempt - 1)) * random.uniform(0.8, 1.2)
time.sleep(delay)
# =========================
# ConcreteDecorator:TTL + LRU 缓存
# =========================
class TTLCache:
"""简单的TTL+LRU缓存实现,用于示例,不考虑并发。"""
def __init__(self, capacity: int = 128, ttl_seconds: float = 5.0):
self.capacity = capacity
self.ttl = ttl_seconds
self.store: OrderedDict[Any, Tuple[float, Any]] = OrderedDict()
def _evict_if_needed(self):
while len(self.store) > self.capacity:
self.store.popitem(last=False)
def _purge_expired(self):
now = time.time()
expired_keys = [k for k, (exp, _) in self.store.items() if exp < now]
for k in expired_keys:
del self.store[k]
def get(self, key: Any) -> Optional[Any]:
self._purge_expired()
if key in self.store:
exp, val = self.store.pop(key) # 触发LRU移动
self.store[key] = (exp, val)
return val
return None
def put(self, key: Any, value: Any):
exp = time.time() + self.ttl
if key in self.store:
del self.store[key]
self.store[key] = (exp, value)
self._evict_if_needed()
class CacheFetcher(FetcherDecorator):
def __init__(self, inner: Fetcher, cache: TTLCache, metrics: Optional[MetricsRegistry] = None):
super().__init__(inner)
self.cache = cache
self.metrics = metrics
def _key(self, url: str, headers: Optional[Dict[str, str]]) -> Tuple[str, Tuple[Tuple[str, str], ...]]:
headers_tuple = tuple(sorted((headers or {}).items()))
return (url, headers_tuple)
def fetch(self, url: str, headers: Optional[Dict[str, str]] = None) -> str:
key = self._key(url, headers)
val = self.cache.get(key)
if val is not None:
if self.metrics:
self.metrics.inc("cache_hits")
return val
if self.metrics:
self.metrics.inc("cache_misses")
val = self._inner.fetch(url, headers=headers)
self.cache.put(key, val)
return val
# =========================
# ConcreteDecorator:度量
# =========================
class MetricsFetcher(FetcherDecorator):
def __init__(self, inner: Fetcher, metrics: MetricsRegistry):
super().__init__(inner)
self.metrics = metrics
def fetch(self, url: str, headers: Optional[Dict[str, str]] = None) -> str:
self.metrics.inc("fetch_calls")
start = time.time()
try:
result = self._inner.fetch(url, headers=headers)
self.metrics.inc("fetch_success")
return result
except Exception:
self.metrics.inc("fetch_failure")
raise
finally:
elapsed_ms = (time.time() - start) * 1000.0
self.metrics.add_time("fetch_latency_ms_total", elapsed_ms)
# =========================
# 演示:构建装饰器调用链并运行
# =========================
if __name__ == "__main__":
# 准备示例数据与度量中心
data = {
"item/42": "The answer is 42.",
"item/7": "Lucky number is 7.",
}
metrics = MetricsRegistry()
# ConcreteComponent
base = UnstableFetcher(data=data, failure_rate=0.5, latency_range=(0.05, 0.15))
# 构建调用链(顺序很重要):
# Cache -> Retry -> CircuitBreaker -> base,最外层再加 Metrics
cache = TTLCache(capacity=64, ttl_seconds=2.0)
chain = MetricsFetcher(
inner=CacheFetcher(
inner=RetryFetcher(
inner=CircuitBreakerFetcher(
inner=base,
failure_threshold=3, # 连续3次失败打开熔断
recovery_time=3.0, # 3秒后进入half-open
metrics=metrics
),
retries=4, # 最多4次补偿重试
backoff_base=0.08, # 初始退避
retry_exceptions=(TransientError,),
giveup_exceptions=(CircuitOpenError, NotFoundError),
metrics=metrics
),
cache=cache,
metrics=metrics
),
metrics=metrics
)
# 连续请求以观察:缓存、重试、熔断与恢复的行为
url = "item/42"
for i in range(1, 12):
try:
val = chain.fetch(url)
print(f"[{i:02d}] OK: {val}")
except CircuitOpenError as e:
print(f"[{i:02d}] CIRCUIT OPEN: {e}")
except NotFoundError as e:
print(f"[{i:02d}] NOT FOUND: {e}")
except TransientError as e:
print(f"[{i:02d}] TRANSIENT FAILURE (no more retries): {e}")
except Exception as e:
print(f"[{i:02d}] OTHER ERROR: {e}")
time.sleep(0.7) # 控制节奏,观察TTL与熔断恢复
print("\nMetrics snapshot:")
print(metrics.snapshot())
要点与实践建议:
帮助用户深入理解并掌握指定设计模式的用途、结构及实现方法,通过清晰的讲解和实例代码提升技术技能,从而解决实际开发中的架构问题,并在项目实施中充分运用到设计模式的核心思想。
从事系统开发的程序员,使用提示词快速掌握设计模式理论,学习代码实现,并将其用于项目开发。
想提升团队架构能力的技术领袖,利用本提示词快速生成教学材料并推广设计模式知识,使团队开发更高效。
从事技术教程、博客、书籍撰写的内容创作者,通过提示词快速建立高质量架构文章模板,提高创作效率。
将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。
把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。
在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。
免费获取高级提示词-优惠即将到期