好的,现代C++(C++11/14/17及以后)中,除了经典的设计模式,还有一些模式因其与现代语言特性的契合而更受推崇。以下是一些特别适合现代C++的设计模式及其优势:
1. 单例模式 (Singleton Pattern)
-
现代实现: 利用
static局部变量(C++11保证线程安全初始化)或std::call_once。 -
优势: 简洁、线程安全。
-
示例:
cppclass Singleton { public: static Singleton& getInstance() { static Singleton instance; // Thread-safe since C++11 return instance; } // ... other members private: Singleton() = default; // Private constructor ~Singleton() = default; Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; };
2. 工厂方法模式 (Factory Method Pattern)
-
现代实现: 结合返回
std::unique_ptr或std::shared_ptr,避免原始指针和手动内存管理。可使用std::function或 lambda 作为工厂函数。 -
优势: 安全的内存管理,灵活的工厂定义。
-
示例:
cppclass Product { public: virtual ~Product() = default; virtual void use() = 0; }; class ConcreteProductA : public Product { ... }; class ConcreteProductB : public Product { ... }; using ProductPtr = std::unique_ptr<Product>; ProductPtr createProduct(const std::string& type) { if (type == "A") return std::make_unique<ConcreteProductA>(); if (type == "B") return std::make_unique<ConcreteProductB>(); return nullptr; }
3. 策略模式 (Strategy Pattern)
-
现代实现: 使用
std::function、lambda 表达式或函数对象代替传统的接口/基类(如果策略逻辑简单)。 -
优势: 减少类层次结构,代码更简洁,易于组合策略。
-
示例:
cppclass Context { std::function<void()> strategy_; public: void setStrategy(std::function<void()> strategy) { strategy_ = std::move(strategy); } void executeStrategy() { if (strategy_) strategy_(); } }; // Usage: Context ctx; ctx.setStrategy([]() { std::cout << "Strategy A\n"; }); ctx.executeStrategy();
4. 观察者模式 (Observer Pattern)
-
现代实现: 使用
std::function+std::vector(信号槽机制),或库如boost::signals2。利用智能指针管理观察者生命周期。 -
优势: 解耦更彻底,支持任意可调用对象作为观察者,避免继承。
-
示例 (简化):
cppclass Subject { std::vector<std::function<void(int)>> observers_; public: void attach(std::function<void(int)> observer) { observers_.push_back(observer); } void notify(int data) { for (auto& obs : observers_) { obs(data); } } };
5. 构建者模式 (Builder Pattern)
-
现代实现: 流畅接口,利用返回值链式调用。可结合
std::optional或结构化绑定处理可选参数。 -
优势: 构造复杂对象时代码可读性好,支持逐步构建和参数验证。
-
示例:
cppclass Pizza { // ... (members like size, toppings, etc.) class Builder { Pizza pizza_; public: Builder& setSize(std::string size) { pizza_.size_ = size; return *this; } Builder& addTopping(std::string topping) { pizza_.toppings_.push_back(topping); return *this; } Pizza build() { return std::move(pizza_); } // Or return a unique_ptr }; }; // Usage: Pizza pizza = Pizza::Builder().setSize("Large").addTopping("Cheese").addTopping("Pepperoni").build();
6. 依赖注入 (Dependency Injection)
-
现代实现: 构造函数注入或Setter注入,结合智能指针(
std::unique_ptr,std::shared_ptr)传递依赖对象。框架如Boost.DI可简化。 -
优势: 提高可测试性、可维护性和松耦合。是现代软件设计的重要原则。
-
示例:
cppclass Service { public: virtual void doWork() = 0; virtual ~Service() = default; }; class Client { std::unique_ptr<Service> service_; public: Client(std::unique_ptr<Service> service) : service_(std::move(service)) {} void execute() { service_->doWork(); } };
7. 适配器模式 (Adapter Pattern)
-
现代实现: 适配新接口到遗留代码或第三方库。常结合
std::function或 lambda 包装调用。 -
优势: 集成新旧代码,无需修改原有接口。
-
示例:
cpp// Legacy interface class LegacyPrinter { public: void printDocument(const char* doc) { ... } }; // Modern interface class ModernPrinter { public: virtual void print(const std::string& doc) = 0; }; // Adapter class LegacyPrinterAdapter : public ModernPrinter { LegacyPrinter legacyPrinter_; public: void print(const std::string& doc) override { legacyPrinter_.printDocument(doc.c_str()); } };
8. 状态模式 (State Pattern)
-
现代实现: 状态对象可使用智能指针管理。结合
std::variant(C++17) 可实现类型安全的状态机(有时称为状态模式的替代)。 -
优势: 封装状态行为,简化状态转换逻辑。
-
示例 (传统状态模式):
cppclass Context; class State { public: virtual void handle(Context* context) = 0; virtual ~State() = default; }; class Context { std::unique_ptr<State> state_; public: void setState(std::unique_ptr<State> state) { state_ = std::move(state); } void request() { if (state_) state_->handle(this); } };
9. 装饰器模式 (Decorator Pattern)
-
现代实现: 利用继承和组合。可结合
std::unique_ptr管理被装饰对象。 -
优势: 动态扩展对象功能,避免子类爆炸。
-
示例:
cppclass Component { public: virtual void operation() = 0; virtual ~Component() = default; }; class ConcreteComponent : public Component { ... }; class Decorator : public Component { protected: std::unique_ptr<Component> component_; public: Decorator(std::unique_ptr<Component> comp) : component_(std::move(comp)) {} void operation() override { component_->operation(); } }; class ConcreteDecoratorA : public Decorator { public: using Decorator::Decorator; void operation() override { Decorator::operation(); // Add extra behavior } };
10. 访问者模式 (Visitor Pattern)
-
现代实现: 虽然实现较复杂,但在需要遍历复杂结构(如AST)并执行多种操作时仍有用。可结合
std::variant和std::visit(C++17) 实现简化版(有时称为std::variant访问者)。 -
优势: 将算法与对象结构分离,便于添加新操作。
-
示例 (传统):
cppclass Element; class Visitor { public: virtual void visit(Element* element) = 0; virtual ~Visitor() = default; }; class Element { public: virtual void accept(Visitor& visitor) = 0; virtual ~Element() = default; }; class ConcreteElementA : public Element { public: void accept(Visitor& visitor) override { visitor.visit(this); } }; // ... ConcreteVisitor implementations
选择建议
- 优先组合而非继承: 现代C++鼓励使用组合、
std::function、lambda 等,减少深度继承层次。 - 善用智能指针:
std::unique_ptr和std::shared_ptr极大简化了资源管理和生命周期控制。 - 利用新特性:
std::optional,std::variant,std::any,std::function, lambda 等特性可以简化或改变某些模式的实现方式。 - 考虑范围库 (Ranges) (C++20): 提供了一种声明式处理序列的新方式,有时可以替代迭代器模式的部分应用。
- 避免过度设计: 设计模式是工具,应在确实需要解决特定问题时才使用,而不是为了用而用。
选择哪种模式取决于具体的应用场景和需要解决的问题。现代C++的特性让许多模式的实现更加简洁、安全和高效。