Decorating Pattern

本文深入探讨了装饰者模式的应用场景及其实现方式,通过对比继承和组合的方式,展示了装饰者模式如何为对象动态地添加职责,同时遵循了类应当对外扩展开放但对修改关闭的设计原则。

Decorate pattern is to give objects new responsibilities without making any code change to the underlying classes. The Decorator Pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Inheritance VS. Composite : When inherit behavior by subclassing, the behavior is set statically at compile time. In addition, all subclasses must inherit the same behavior. If however, choose to extend the object's behavior through composition, then, this will be done dynamically. By dynamically composing objects, add new functionality by writing new code rather than altering existing code. Not to change code can lower the chance of introducing bugs or causing unintended side effects in pre-existing code.

Design Principle: Classes should be open for extension, but closed for modification. 

Design a Coffee shop electronic menu: 

we have HouseBlend, DarkRoast, Espresso, and Decaf coffee, On top of each coffee, customer can add milk and mocha decorator.


If we design our system like this, in the future, whenever we add some new flavour, we will need a subclass.... This is pretty bad design.

Think that if we don't use decorator design patter, our design can will behave like this:



1: why use condimentDecorator?

The scenario to use decorator pattern is that there is already an abstract Beverage class. Traditionally the Decorator Pattern does specify an abstract component to try to avoid altering existing code.

2: when to use Decorator Pattern?

The pattern is used at any time to add new behavior. If we relied on interitance, we will have to go in and change existing code any time we want to add new behaviors. This disobeys the OOD principle.

3: Dynamic vs Static

if we rely on inheritance, then our behavior can only be determined statically at compile time. In other words, we get only behavior the superclass gives us or that we override. With composition, we can mix and match decorators any way we like....at RUMTIME!

#include "../header.h"
using namespace std;

class Beverage {
protected:
  string description = "Unknown Beverage";
public:
  Beverage() {}
  ~Beverage() {}
  virtual string getDescription() {
    return description;
  }
  virtual double getCost() = 0;
  virtual void test() {
    cout << "test" << endl;
  }
};

class HouseBlend : public Beverage {
public:
  HouseBlend() {
    description = "HouseBlend";
  }
  ~HouseBlend() {}
  double getCost() {
    return 0.1;
  }
};

class Mocha : public Beverage {
public:
  Mocha() {description = "Mocha";}
  ~Mocha() {}
  double getCost() {
    return 0.2;
  }
};

class BeverageDecorator : public Beverage {
public:
  virtual string getDescription() = 0;
  virtual double getCost() = 0;
};

class Cream : public BeverageDecorator {
private:
  Beverage* beverage;
public:
  Cream(Beverage* b) {beverage = b;}
  ~Cream() {}
  string getDescription() {
    return "cream, " + beverage->getDescription();
  }
  double getCost() {
    return 0.01 + beverage->getCost();
  }
};

class Soy : public BeverageDecorator {
private:
  Beverage* beverage;
public:
  Soy(Beverage* b) {beverage = b;}
  ~Soy() {}
  string getDescription() {
    return "soy, " + beverage->getDescription();
  }
  double getCost() {
    return 0.02 + beverage->getCost();
  }
};

int main(void) {
  Beverage* beverage = new HouseBlend();
  beverage = new Cream(beverage);
  beverage = new Soy(beverage);
  cout << beverage->getDescription() << endl;
  cout << beverage->getCost() << endl;
  beverage->test();
}

<think>我们正在讨论如何装饰SCF(Serverless Cloud Function)对象。在无服务器云函数中,装饰通常指的是在函数执行前后添加额外的逻辑,比如日志记录、性能监控、参数校验等,而不修改函数的核心业务代码。这类似于面向切面编程(AOP)的概念。 在腾讯云SCF中,我们可以通过编写装饰器函数(在Python中)或使用中间件(在Node.js等语言中)来实现。下面以Python为例,展示如何通过装饰器来增强SCF函数的功能。 ### 装饰器模式在SCF中的应用 装饰器模式允许我们在不修改原函数代码的情况下,为函数添加额外的功能。例如,我们可以创建一个装饰器来记录函数的执行时间。 #### 示例:记录函数执行时间的装饰器 ```python import time import logging logger = logging.getLogger() def timer_decorator(func): def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) # 调用原函数 end_time = time.time() logger.info(f"Function {func.__name__} executed in {end_time - start_time:.4f} seconds") return result return wrapper # 使用装饰器 @timer_decorator def main_handler(event, context): # 你的业务逻辑 return "Hello World" ``` 在这个例子中,`timer_decorator`装饰器会记录被装饰函数的执行时间,并通过日志输出。 #### 参数校验装饰器 另一个常见的用途是参数校验。例如,我们可以检查事件中是否包含必要的字段。 ```python def validate_params(required_params): def decorator(func): def wrapper(event, context): for param in required_params: if param not in event: raise ValueError(f"Missing required parameter: {param}") return func(event, context) return wrapper return decorator # 使用装饰器,指定需要校验的参数 @validate_params(['name', 'age']) def main_handler(event, context): # 这里可以安全地使用event['name']和event['age'] return f"Hello {event['name']}, your age is {event['age']}" ``` ### 在SCF中使用中间件 对于Node.js,我们可以使用中间件模式。腾讯云SCF支持使用Web框架(如Express、Koa)来构建应用,因此可以使用这些框架的中间件机制。 #### 示例:使用Express中间件 ```javascript const express = require('express'); const app = express(); // 中间件:记录请求时间 app.use((req, res, next) => { const start = Date.now(); next(); // 执行下一个中间件或路由处理函数 const duration = Date.now() - start; console.log(`Request to ${req.path} took ${duration}ms`); }); // 路由 app.get('/', (req, res) => { res.send('Hello World'); }); // 将Express应用导出为SCF函数 module.exports = app; ``` ### 注意事项 1. **性能影响**:装饰器或中间件会增加额外的开销,应确保其不会对函数性能产生显著影响。 2. **错误处理**:在装饰器中,应妥善处理异常,避免影响函数的正常执行。 3. **资源清理**:如果装饰器中涉及资源(如数据库连接),应确保在函数执行结束后正确清理。 ### 相关问题 1. 如何在SCF中实现日志记录和监控? 2. SCF函数如何做参数校验? 3. 在SCF中使用装饰器模式有哪些优缺点? 4. 如何为SCF函数添加统一的错误处理机制? 5. 在Node.js的SCF函数中,如何使用中间件进行请求处理? 以上内容提供了在无服务器云函数中装饰函数的基本方法,并给出了具体示例。通过装饰器或中间件,我们可以将横切关注点(如日志、监控、校验)与业务逻辑分离,提高代码的可维护性和复用性。</think>### 如何装饰无服务器云函数(SCF)对象 在无服务器架构中,装饰 SCF 对象指通过**非侵入式增强**为函数添加横切关注点(如日志、监控、安全等),同时保持业务代码纯净。以下是关键方法: #### 1. **中间件装饰模式**(推荐) 通过高阶函数包装 SCF 主逻辑,实现装饰层: ```python # 装饰器:日志记录 def log_decorator(handler): def wrapper(event, context): print(f"📝 请求事件: {event}") result = handler(event, context) # 执行原函数 print(f"✅ 响应结果: {result}") return result return wrapper # 装饰器:性能监控 def monitor_decorator(handler): def wrapper(event, context): start = time.time() result = handler(event, context) duration = (time.time() - start) * 1000 print(f"⏱️ 执行耗时: {duration:.2f}ms") return result return wrapper # 应用装饰器 @monitor_decorator @log_decorator def main_handler(event, context): # 纯净的业务逻辑 return {"message": "Hello SCF"} ``` #### 2. **SCF 层扩展** 利用云平台原生能力: - **日志服务**:自动捕获 stdout/stderr 输出(无需代码修改)[^3] - **触发器配置**:通过 API 网关前置处理请求(参数校验/限流) - **环境变量**:动态注入配置参数 ```yaml # serverless.yml 配置示例 provider: environment: RATE_LIMIT: 100 # 限流阈值 ``` #### 3. **外部服务集成** - **监控埋点**:连接云监控(Cloud Monitor)自动采集指标[^3] - **安全增强**:通过 CAM 策略实现函数级权限控制 - **配置中心**:从 Consul 或云平台参数存储拉取运行时配置 #### 4. **错误处理装饰** 统一捕获异常并格式化响应: ```python def error_handler(handler): def wrapper(event, context): try: return handler(event, context) except Exception as e: # 统一错误格式 return { "errorCode": 500, "errorMsg": f"SCF执行失败: {str(e)}" } return wrapper ``` ### 典型应用场景 1. **参数校验**:验证输入事件结构 ```python def validate_schema(schema): def decorator(handler): def wrapper(event, context): if not validate(event, schema): # 校验逻辑 raise ValueError("非法参数") return handler(event, context) return wrapper return decorator ``` 2. **限流控制**:基于令牌桶限制调用频率[^3] 3. **数据转换**:XML/JSON 自动转换 4. **认证授权**:JWT 令牌验证前置层 ### 注意事项 1. **冷启动影响**:避免装饰器引入重型依赖(如数据库连接) 2. **版本兼容**:检查装饰器与云函数运行环境的兼容性[^4] 3. **资源清理**:在异步场景中确保装饰器释放资源 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值