23种设计模式的现代C++17实现
目录
| 类型 | 模式 |
|---|---|
| 创建型 | 单例、工厂方法、抽象工厂、建造者、原型 |
| 结构型 | 适配器、桥接、组合、装饰、外观、享元、代理 |
| 行为型 | 责任链、命令、解释器、迭代器、中介者、备忘录、观察者、状态、策略、模板方法、访问者 |
一、创建型模式
1. 单例模式 (Singleton)
意图:确保类只有一个实例,提供全局访问点
场景:配置中心、日志系统、数据库连接池
#include <iostream>
#include <string>
class Singleton {
public:
static Singleton& instance() {
static Singleton s; // C++11起线程安全
return s;
}
void setData(const std::string& d) { data_ = d; }
std::string getData() const { return data_; }
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
Singleton() = default;
std::string data_;
};
int main() {
Singleton::instance().setData("Hello");
std::cout << Singleton::instance().getData() << std::endl;
// 验证单例
auto& s1 = Singleton::instance();
auto& s2 = Singleton::instance();
std::cout << "Same: " << (&s1 == &s2) << std::endl;
return 0;
}
2. 工厂方法 (Factory Method)
意图:定义创建对象的接口,让子类决定实例化哪个类
场景:需要延迟实例化、创建逻辑复杂
#include <iostream>
#include <memory>
#include <string_view>
#include <optional>
class Product {
public:
virtual ~Product() = default;
virtual void use() = 0;
};
class ProductA : public Product {
public:
void use() override { std::cout << "Product A\n"; }
};
class ProductB : public Product {
public:
void use() override { std::cout << "Product B\n"; }
};
// C++17: 使用string_view和optional的工厂
class Factory {
public:
static std::optional<std::unique_ptr<Product>> create(std::string_view type) {
if (type == "A") return std::make_unique<ProductA>();
if (type == "B") return std::make_unique<ProductB>();
return std::nullopt;
}
};
// 泛型工厂
template<typename T, typename... Args>
auto make(Args&&... args) {
return std::make_unique<T>(std::forward<Args>(args)...);
}
int main() {
if (auto p = Factory::create("A")) {
(*p)->use();
}
auto product = make<ProductB>();
product->use();
return 0;
}
3. 抽象工厂 (Abstract Factory)
意图:创建相关对象家族,无需指定具体类
场景:跨平台UI、数据库访问层
#include <iostream>
#include <memory>
#include <string_view>
class Button {
public:
virtual ~Button() = default;
virtual void click() = 0;
};
class TextBox {
public:
virtual ~TextBox() = default;
virtual void input(std::string_view text) = 0;
};
// Windows产品族
class WinButton : public Button {
public:
void click() override { std::cout << "Win Button\n"; }
};
class WinTextBox : public TextBox {
public:
void input(std::string_view text) override {
std::cout << "Win TextBox: " << text << "\n";
}
};
// Mac产品族
class MacButton : public Button {
public:
void click() override { std::cout << "Mac Button\n"; }
};
class MacTextBox : public TextBox {
public:
void input(std::string_view text) override {
std::cout << "Mac TextBox: " << text << "\n";
}
};
// C++17: 模板工厂
template<typename ButtonT, typename TextBoxT>
class Factory {
public:
static_assert(std::is_base_of_v<Button, ButtonT>);
static_assert(std::is_base_of_v<TextBox, TextBoxT>);
auto createButton() { return std::make_unique<ButtonT>(); }
auto createTextBox() { return std::make_unique<TextBoxT>(); }
};
using WinFactory = Factory<WinButton, WinTextBox>;
using MacFactory = Factory<MacButton, MacTextBox>;
int main() {
WinFactory win;
auto btn = win.createButton();
btn->click();
MacFactory mac;
auto txt = mac.createTextBox();
txt->input("Hello");
return 0;
}
4. 建造者模式 (Builder)
意图:分步骤构建复杂对象
场景:对象构造参数多、需要不同配置
#include <iostream>
#include <string>
#include <optional>
struct Computer {
std::string cpu;
std::string ram;
std::string ssd;
void show() const {
std::cout << cpu << ", " << ram << ", " << ssd << "\n";
}
};
// C++17: 使用optional的严格建造者
class Builder {
public:
Builder& cpu(std::string_view c) { cpu_ = std::string(c); return *this; }
Builder& ram(std::string_view r) { ram_ = std::string(r); return *this; }
Builder& ssd(std::string_view s) { ssd_ = std::string(s); return *this; }
std::optional<Computer> build() {
if (!cpu_ || !ram_) return std::nullopt;
return Computer{*cpu_, *ram_, ssd_.value_or("256GB")};
}
private:
std::optional<std::string> cpu_;
std::optional<std::string> ram_;
std::optional<std::string> ssd_;
};
// 结构化绑定应用
auto createPC() {
return std::make_tuple(std::string("i9"), std::string("64GB"), std::string("2TB"));
}
int main() {
auto pc = Builder{}.cpu("i7").ram("32GB").ssd("1TB").build();
if (pc) pc->show();
// 结构化绑定
auto [cpu, ram, ssd] = createPC();
Computer pc2{cpu, ram, ssd};
pc2.show();
return 0;
}
5. 原型模式 (Prototype)
意图:通过复制现有对象创建新对象
场景:对象创建成本高、需要保存状态
#include <iostream>
#include <memory>
#include <string_view>
#include <unordered_map>
// CRTP自动克隆
template<typename Derived>
class Cloneable {
public:
std::unique_ptr<Derived> clone() const {
return std::make_unique<Derived>(static_cast<const Derived&>(*this));
}
};
class Document : public Cloneable<Document> {
public:
explicit Document(std::string_view title) : title_(title) {}
void show() const { std::cout << title_ << "\n"; }
void setTitle(std::string_view t) { title_ = t; }
private:
std::string title_;
};
// C++17: inline变量的注册表
class Registry {
public:
static Registry& instance() {
static Registry r;
return r;
}
void add(std::string_view name, std::unique_ptr<Document> doc) {
prototypes_[std::string(name)] = std::move(doc);
}
std::unique_ptr<Document> create(std::string_view name) {
auto it = prototypes_.find(std::string(name));
return (it != prototypes_.end()) ? it->second->clone() : nullptr;
}
private:
Registry() = default;
std::unordered_map<std::string, std::unique_ptr<Document>> prototypes_;
};
int main() {
Document doc1("Report");
auto doc2 = doc1.clone();
doc1.show();
doc2->show();
// 使用注册表
Registry::instance().add("template", std::make_unique<Document>("Template"));
auto doc3 = Registry::instance().create("template");
if (doc3) doc3->show();
return 0;
}
二、结构型模式
6. 适配器模式 (Adapter)
意图:将一个接口转换成客户希望的另一个接口
场景:复用旧类、统一不同接口
#include <iostream>
#include <memory>
#include <string_view>
class Target {
public:
virtual ~Target() = default;
virtual void request(std::string_view data) = 0;
};
class Adaptee {
public:
void specificRequest(std::string_view data) {
std::cout << "Adaptee: " << data << "\n";
}
};
// C++17: 使用string_view的适配器
class Adapter : public Target {
public:
explicit Adapter(std::unique_ptr<Adaptee> a) : adaptee_(std::move(a)) {}
void request(std::string_view data) override {
adaptee_->specificRequest(data);
}
private:
std::unique_ptr<Adaptee> adaptee_;
};
int main() {
auto adapter = std::make_unique<Adapter>(std::make_unique<Adaptee>());
adapter->request("Hello");
return 0;
}
7. 桥接模式 (Bridge)
意图:分离抽象与实现,使它们可独立变化
场景:多维度变化、避免类爆炸
#include <iostream>
#include <memory>
class Implementation {
public:
virtual ~Implementation() = default;
virtual void operationImpl() = 0;
};
class ConcreteImplA : public Implementation {
public:
void operationImpl() override { std::cout << "Implementation A\n"; }
};
class ConcreteImplB : public Implementation {
public:
void operationImpl() override { std::cout << "Implementation B\n"; }
};
class Abstraction {
public:
explicit Abstraction(std::unique_ptr<Implementation> impl)
: impl_(std::move(impl)) {}
virtual void operation() {
impl_->operationImpl();
}
protected:
std::unique_ptr<Implementation> impl_;
};
class ExtendedAbstraction : public Abstraction {
public:
using Abstraction::Abstraction;
void operation() override {
std::cout << "Extended: ";
impl_->operationImpl();
}
};
int main() {
Abstraction a(std::make_unique<ConcreteImplA>());
a.operation();
ExtendedAbstraction b(std::make_unique<ConcreteImplB>());
b.operation();
return 0;
}
8. 组合模式 (Composite)
意图:将对象组合成树形结构表示”部分-整体”层次
场景:文件系统、UI组件树
#include <iostream>
#include <vector>
#include <variant>
#include <memory>
#include <string>
struct File {
std::string name;
size_t size;
};
class Directory;
using Node = std::variant<File, std::shared_ptr<Directory>>;
class Directory {
public:
explicit Directory(std::string n) : name_(std::move(n)) {}
void add(Node node) { children_.push_back(std::move(node)); }
// C++17: 使用std::visit
void display(int indent = 0) const {
std::cout << std::string(indent, ' ') << name_ << "/\n";
for (const auto& child : children_) {
std::visit([indent](const auto& item) {
using T = std::decay_t<decltype(item)>;
if constexpr (std::is_same_v<T, File>) {
std::cout << std::string(indent + 2, ' ')
<< item.name << " (" << item.size << ")\n";
} else {
item->display(indent + 2);
}
}, child);
}
}
private:
std::string name_;
std::vector<Node> children_;
};
int main() {
auto root = std::make_shared<Directory>("root");
root->add(File{"a.txt", 100});
auto dir = std::make_shared<Directory>("subdir");
dir->add(File{"b.txt", 200});
root->add(dir);
root->display();
return 0;
}
9. 装饰器模式 (Decorator)
意图:动态地给对象添加额外职责
场景:扩展功能、避免子类爆炸
#include <iostream>
#include <memory>
#include <functional>
class Component {
public:
virtual ~Component() = default;
virtual void operation() = 0;
};
class ConcreteComponent : public Component {
public:
void operation() override { std::cout << "Base"; }
};
class Decorator : public Component {
public:
explicit Decorator(std::unique_ptr<Component> c) : component_(std::move(c)) {}
void operation() override {
component_->operation();
}
protected:
std::unique_ptr<Component> component_;
};
class ConcreteDecoratorA : public Decorator {
public:
using Decorator::Decorator;
void operation() override {
std::cout << "[";
Decorator::operation();
std::cout << "]";
}
};
class ConcreteDecoratorB : public Decorator {
public:
using Decorator::Decorator;
void operation() override {
std::cout << "{";
Decorator::operation();
std::cout << "}";
}
};
// C++17: 使用lambda的装饰器
class LambdaDecorator : public Component {
public:
LambdaDecorator(std::unique_ptr<Component> c,
std::function<void()> before,
std::function<void()> after)
: component_(std::move(c)), before_(before), after_(after) {}
void operation() override {
before_();
component_->operation();
after_();
}
private:
std::unique_ptr<Component> component_;
std::function<void()> before_;
std::function<void()> after_;
};
int main() {
auto c = std::make_unique<ConcreteComponent>();
auto d1 = std::make_unique<ConcreteDecoratorA>(std::move(c));
auto d2 = std::make_unique<ConcreteDecoratorB>(std::move(d1));
d2->operation();
std::cout << "\n";
// Lambda装饰器
auto base = std::make_unique<ConcreteComponent>();
auto decorated = std::make_unique<LambdaDecorator>(
std::move(base),
[]() { std::cout << "Before-"; },
[]() { std::cout << "-After"; }
);
decorated->operation();
std::cout << "\n";
return 0;
}
10. 外观模式 (Facade)
意图:为子系统提供统一的高层接口
场景:简化复杂系统、分层架构
#include <iostream>
#include <tuple>
#include <string_view>
class SubsystemA {
public:
void operationA() { std::cout << "Subsystem A\n"; }
};
class SubsystemB {
public:
void operationB() { std::cout << "Subsystem B\n"; }
};
class SubsystemC {
public:
void operationC() { std::cout << "Subsystem C\n"; }
};
// C++17: 简化接口 + 结构化绑定
class Facade {
public:
void simpleOperation() {
std::cout << "=== Start ===\n";
a_.operationA();
b_.operationB();
c_.operationC();
std::cout << "=== End ===\n";
}
// 结构化绑定返回多值
auto getStatus() {
return std::make_tuple(true, 42, std::string("OK"));
}
private:
SubsystemA a_;
SubsystemB b_;
SubsystemC c_;
};
int main() {
Facade f;
f.simpleOperation();
auto [ok, code, msg] = f.getStatus();
std::cout << "Status: " << ok << ", " << code << ", " << msg << "\n";
return 0;
}
11. 享元模式 (Flyweight)
意图:运用共享技术有效支持大量细粒度对象
场景:文字编辑器字符、游戏粒子
#include <iostream>
#include <unordered_map>
#include <memory>
#include <string_view>
#include <shared_mutex>
#include <mutex>
class TreeType {
public:
TreeType(std::string_view n, std::string_view c)
: name_(n), color_(c) {}
void draw(int x, int y) const {
std::cout << name_ << " (" << color_ << ") at (" << x << ", " << y << ")\n";
}
private:
std::string name_;
std::string color_;
};
// C++17: 线程安全享元工厂
template<typename T>
class FlyweightFactory {
public:
std::shared_ptr<T> get(std::string_view key) {
{
std::shared_lock lock(mutex_);
auto it = cache_.find(std::string(key));
if (it != cache_.end()) return it->second;
}
std::unique_lock lock(mutex_);
auto it = cache_.find(std::string(key));
if (it != cache_.end()) return it->second;
auto obj = std::make_shared<T>(key, "Green");
cache_[std::string(key)] = obj;
return obj;
}
private:
std::unordered_map<std::string, std::shared_ptr<T>> cache_;
std::shared_mutex mutex_;
};
// C++17: inline变量的全局工厂
class TreeFactory {
public:
static TreeFactory& instance() {
static TreeFactory f;
return f;
}
auto get(std::string_view name) {
return factory_.get(name);
}
private:
TreeFactory() = default;
FlyweightFactory<TreeType> factory_;
};
int main() {
// 创建100棵树,实际只创建2种类型
for (int i = 0; i < 50; ++i) {
TreeFactory::instance().get("Oak");
}
for (int i = 0; i < 50; ++i) {
TreeFactory::instance().get("Pine");
}
auto oak = TreeFactory::instance().get("Oak");
oak->draw(10, 20);
return 0;
}
12. 代理模式 (Proxy)
意图:为对象提供代理以控制访问
场景:延迟加载、访问控制、缓存
#include <iostream>
#include <memory>
#include <optional>
#include <functional>
class Subject {
public:
virtual ~Subject() = default;
virtual void request() = 0;
};
class RealSubject : public Subject {
public:
RealSubject() { std::cout << "RealSubject created\n"; }
void request() override { std::cout << "RealSubject request\n"; }
};
// 虚代理:延迟加载
class Proxy : public Subject {
public:
void request() override {
if (!realSubject_) {
realSubject_ = std::make_unique<RealSubject>();
}
realSubject_->request();
}
private:
std::unique_ptr<RealSubject> realSubject_;
};
// C++17: 使用optional的延迟加载
template<typename T>
class Lazy {
public:
explicit Lazy(std::function<std::unique_ptr<T>()> f) : factory_(f) {}
T& get() {
if (!instance_) instance_ = factory_();
return *instance_;
}
private:
std::function<std::unique_ptr<T>()> factory_;
std::unique_ptr<T> instance_;
};
int main() {
Proxy proxy;
std::cout << "Proxy created\n";
proxy.request(); // 此时才创建RealSubject
proxy.request();
// Lazy代理
Lazy<std::string> lazy([]() {
std::cout << "Creating string...\n";
return std::make_unique<std::string>("Hello");
});
std::cout << "Lazy created\n";
std::cout << lazy.get() << "\n";
return 0;
}
三、行为型模式
13. 责任链模式 (Chain of Responsibility)
意图:让多个对象有机会处理请求
场景:审批流程、事件处理
#include <iostream>
#include <functional>
#include <vector>
#include <optional>
// C++17: 使用折叠表达式的处理链
template<typename... Handlers>
class Chain {
public:
explicit Chain(Handlers... h) : handlers_{h...} {}
template<typename T>
bool process(T&& req) {
return (std::get<Handlers>(handlers_)(std::forward<T>(req)) || ...);
}
private:
std::tuple<Handlers...> handlers_;
};
// C++17: 使用optional的类型安全链
template<typename T>
class TypedChain {
public:
using Handler = std::function<std::optional<T>(const T&)>;
void add(Handler h) { handlers_.push_back(h); }
std::optional<T> execute(const T& input) {
T current = input;
for (const auto& h : handlers_) {
auto result = h(current);
if (result) return result;
}
return std::nullopt;
}
private:
std::vector<Handler> handlers_;
};
int main() {
auto h1 = [](int x) {
if (x < 10) { std::cout << "H1 handled " << x << "\n"; return true; }
return false;
};
auto h2 = [](int x) {
if (x < 100) { std::cout << "H2 handled " << x << "\n"; return true; }
return false;
};
auto h3 = [](int x) {
std::cout << "H3 (default) handled " << x << "\n";
return true;
};
Chain chain(h1, h2, h3);
chain.process(5);
chain.process(50);
chain.process(500);
return 0;
}
14. 命令模式 (Command)
意图:将请求封装为对象
场景:撤销/重做、队列请求、事务
#include <iostream>
#include <functional>
#include <vector>
#include <stack>
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
virtual void undo() = 0;
};
// C++17: 使用lambda的命令
class LambdaCommand : public Command {
public:
LambdaCommand(std::function<void()> exe, std::function<void()> undo)
: execute_(exe), undo_(undo) {}
void execute() override { execute_(); }
void undo() override { undo_(); }
private:
std::function<void()> execute_;
std::function<void()> undo_;
};
// 宏命令
template<typename... Cmds>
class MacroCommand : public Command {
public:
explicit MacroCommand(Cmds... cmds) : commands_{cmds...} {}
void execute() override {
std::apply([](auto&... cmd) { (cmd.execute(), ...); }, commands_);
}
void undo() override {
std::apply([](auto&... cmd) { (cmd.undo(), ...); }, commands_);
}
private:
std::tuple<Cmds...> commands_;
};
class Invoker {
public:
void execute(std::unique_ptr<Command> cmd) {
cmd->execute();
history_.push(std::move(cmd));
}
void undo() {
if (!history_.empty()) {
history_.top()->undo();
history_.pop();
}
}
private:
std::stack<std::unique_ptr<Command>> history_;
};
int main() {
int value = 0;
Invoker invoker;
// 使用lambda创建命令
auto add = std::make_unique<LambdaCommand>(
[&]() { value++; std::cout << "Add: " << value << "\n"; },
[&]() { value--; std::cout << "Undo: " << value << "\n"; }
);
invoker.execute(std::move(add));
invoker.undo();
return 0;
}
15. 解释器模式 (Interpreter)
意图:定义文法表示和解释器
场景:DSL、规则引擎
#include <iostream>
#include <variant>
#include <string_view>
#include <unordered_map>
#include <functional>
using Value = std::variant<int, double, bool>;
class Context {
public:
void set(std::string_view name, Value val) {
vars_[std::string(name)] = val;
}
Value get(std::string_view name) const {
auto it = vars_.find(std::string(name));
return (it != vars_.end()) ? it->second : Value{0};
}
private:
std::unordered_map<std::string, Value> vars_;
};
// C++17: 使用visit的解释器
template<typename T>
T interpret(const Context& ctx, const std::variant<T, std::string_view>& expr) {
return std::visit([&ctx](auto&& val) -> T {
using U = std::decay_t<decltype(val)>;
if constexpr (std::is_same_v<U, T>) {
return val;
} else {
auto result = ctx.get(val);
return std::get<T>(result);
}
}, expr);
}
// C++17: constexpr计算
constexpr int eval(char op, int a, int b) {
switch (op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
default: return 0;
}
}
int main() {
Context ctx;
ctx.set("x", 10);
ctx.set("y", 20);
std::variant<int, std::string_view> expr = "x";
std::cout << "Value: " << interpret<int>(ctx, expr) << "\n";
constexpr int result = eval('+', 3, 5);
std::cout << "3 + 5 = " << result << "\n";
return 0;
}
16. 迭代器模式 (Iterator)
意图:顺序访问聚合对象元素
场景:自定义集合遍历
#include <iostream>
#include <vector>
#include <memory>
// C++17: 简化迭代器,使用范围for支持
template<typename T>
class Container {
public:
void add(T val) { data_.push_back(std::move(val)); }
// 标准迭代器接口
auto begin() { return data_.begin(); }
auto end() { return data_.end(); }
auto begin() const { return data_.begin(); }
auto end() const { return data_.end(); }
// C++17: 结构化绑定支持
auto getData() const { return std::make_tuple(data_.size(), data_.capacity()); }
private:
std::vector<T> data_;
};
// C++17: 自定义范围
template<typename T>
class Range {
public:
Range(T start, T end, T step = 1)
: start_(start), end_(end), step_(step) {}
class Iterator {
public:
Iterator(T val, T step) : val_(val), step_(step) {}
T operator*() const { return val_; }
Iterator& operator++() { val_ += step_; return *this; }
bool operator!=(const Iterator& o) const { return val_ < o.val_; }
private:
T val_, step_;
};
Iterator begin() const { return Iterator(start_, step_); }
Iterator end() const { return Iterator(end_, step_); }
private:
T start_, end_, step_;
};
int main() {
Container<int> c;
c.add(1);
c.add(2);
c.add(3);
// 范围for
for (auto& item : c) {
std::cout << item << " ";
}
std::cout << "\n";
// 结构化绑定
auto [size, cap] = c.getData();
std::cout << "Size: " << size << ", Cap: " << cap << "\n";
// 自定义范围
std::cout << "Range: ";
for (auto i : Range(0, 10, 2)) {
std::cout << i << " ";
}
std::cout << "\n";
return 0;
}
17. 中介者模式 (Mediator)
意图:封装对象交互,减少耦合
场景:聊天室、机场调度、MVC控制器
#include <iostream>
#include <memory>
#include <vector>
#include <string>
#include <algorithm>
class Colleague;
class Mediator {
public:
virtual ~Mediator() = default;
virtual void send(const std::string& msg, Colleague* sender) = 0;
};
class Colleague {
public:
explicit Colleague(Mediator* m) : mediator_(m) {}
virtual ~Colleague() = default;
void send(const std::string& msg) {
mediator_->send(msg, this);
}
virtual void receive(const std::string& msg) = 0;
void setName(std::string n) { name_ = std::move(n); }
std::string getName() const { return name_; }
protected:
Mediator* mediator_;
std::string name_;
};
// C++17: 使用string_view优化
class ChatRoom : public Mediator {
public:
void add(Colleague* c) { colleagues_.push_back(c); }
void send(const std::string& msg, Colleague* sender) override {
for (auto* c : colleagues_) {
if (c != sender) {
c->receive("[" + sender->getName() + "]: " + msg);
}
}
}
private:
std::vector<Colleague*> colleagues_;
};
class User : public Colleague {
public:
using Colleague::Colleague;
void receive(const std::string& msg) override {
std::cout << name_ << " received: " << msg << "\n";
}
};
int main() {
ChatRoom room;
User u1(&room);
u1.setName("Alice");
room.add(&u1);
User u2(&room);
u2.setName("Bob");
room.add(&u2);
User u3(&room);
u3.setName("Charlie");
room.add(&u3);
u1.send("Hello everyone!");
return 0;
}
18. 备忘录模式 (Memento)
意图:捕获对象状态以便恢复
场景:撤销操作、保存游戏、事务回滚
#include <iostream>
#include <string>
#include <vector>
#include <memory>
// C++17: 使用结构化绑定的备忘录
class Memento {
public:
explicit Memento(std::string state) : state_(std::move(state)) {}
std::string getState() const { return state_; }
private:
std::string state_;
};
class Originator {
public:
void setState(std::string s) {
state_ = std::move(s);
std::cout << "State set to: " << state_ << "\n";
}
std::string getState() const { return state_; }
std::unique_ptr<Memento> save() {
return std::make_unique<Memento>(state_);
}
void restore(const Memento* m) {
state_ = m->getState();
std::cout << "State restored to: " << state_ << "\n";
}
// C++17: 返回多个状态
auto getDetails() const {
return std::make_tuple(state_, state_.length());
}
private:
std::string state_;
};
class Caretaker {
public:
void add(std::unique_ptr<Memento> m) {
history_.push_back(std::move(m));
}
const Memento* get(size_t index) const {
if (index < history_.size()) return history_[index].get();
return nullptr;
}
void undo(Originator& o) {
if (history_.size() > 1) {
history_.pop_back();
o.restore(history_.back().get());
}
}
private:
std::vector<std::unique_ptr<Memento>> history_;
};
int main() {
Originator originator;
Caretaker caretaker;
originator.setState("State1");
caretaker.add(originator.save());
originator.setState("State2");
caretaker.add(originator.save());
originator.setState("State3");
// 撤销
caretaker.undo(originator);
// 结构化绑定
auto [state, len] = originator.getDetails();
std::cout << "Current: " << state << " (" << len << " chars)\n";
return 0;
}
19. 观察者模式 (Observer)
意图:对象间一对多依赖,状态改变通知
场景:事件监听、消息订阅、MVC模式
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
#include <string>
class Observer;
class Subject {
public:
virtual ~Subject() = default;
void attach(std::weak_ptr<Observer> o);
void detach(std::weak_ptr<Observer> o);
void notify();
void setState(int s) { state_ = s; notify(); }
int getState() const { return state_; }
private:
std::vector<std::weak_ptr<Observer>> observers_;
int state_ = 0;
};
class Observer : public std::enable_shared_from_this<Observer> {
public:
virtual ~Observer() = default;
virtual void update(int state) = 0;
void subscribe(std::shared_ptr<Subject> s);
};
void Subject::attach(std::weak_ptr<Observer> o) {
observers_.push_back(o);
}
void Subject::detach(std::weak_ptr<Observer> o) {
observers_.erase(
std::remove_if(observers_.begin(), observers_.end(),
[&o](const std::weak_ptr<Observer>& obs) {
return obs.lock() == o.lock();
}),
observers_.end()
);
}
void Subject::notify() {
for (auto it = observers_.begin(); it != observers_.end();) {
if (auto obs = it->lock()) {
obs->update(state_);
++it;
} else {
it = observers_.erase(it); // 清理过期观察者
}
}
}
void Observer::subscribe(std::shared_ptr<Subject> s) {
s->attach(weak_from_this());
}
class ConcreteObserver : public Observer {
public:
explicit ConcreteObserver(std::string n) : name_(std::move(n)) {}
void update(int state) override {
std::cout << name_ << " received update: " << state << "\n";
}
private:
std::string name_;
};
int main() {
auto subject = std::make_shared<Subject>();
auto obs1 = std::make_shared<ConcreteObserver>("Observer1");
auto obs2 = std::make_shared<ConcreteObserver>("Observer2");
obs1->subscribe(subject);
obs2->subscribe(subject);
subject->setState(10);
subject->setState(20);
return 0;
}
20. 状态模式 (State)
意图:对象内部状态改变时改变行为
场景:状态机、游戏角色状态、订单状态
#include <iostream>
#include <memory>
#include <variant>
#include <functional>
class Context;
// C++17: 使用variant的状态
struct StateA;
struct StateB;
using State = std::variant<StateA, StateB>;
struct StateA {
void handle(Context& ctx);
std::string getName() const { return "StateA"; }
};
struct StateB {
void handle(Context& ctx);
std::string getName() const { return "StateB"; }
};
class Context {
public:
Context() : state_(StateA{}) {}
void request() {
std::visit([this](auto& s) {
s.handle(*this);
}, state_);
}
void setState(State s) { state_ = std::move(s); }
std::string getStateName() const {
return std::visit([](const auto& s) { return s.getName(); }, state_);
}
private:
State state_;
};
void StateA::handle(Context& ctx) {
std::cout << "StateA handling, switching to StateB\n";
ctx.setState(StateB{});
}
void StateB::handle(Context& ctx) {
std::cout << "StateB handling, switching to StateA\n";
ctx.setState(StateA{});
}
// C++17: if constexpr的状态机
template<typename StateT>
class SimpleStateMachine {
public:
void handle() {
if constexpr (std::is_same_v<StateT, struct Idle>) {
std::cout << "Idle state\n";
} else if constexpr (std::is_same_v<StateT, struct Running>) {
std::cout << "Running state\n";
}
}
};
struct Idle {};
struct Running {};
int main() {
Context ctx;
std::cout << "Initial: " << ctx.getStateName() << "\n";
ctx.request();
std::cout << "Current: " << ctx.getStateName() << "\n";
ctx.request();
std::cout << "Current: " << ctx.getStateName() << "\n";
// if constexpr版本
SimpleStateMachine<Idle> sm;
sm.handle();
return 0;
}
21. 策略模式 (Strategy)
意图:定义算法族,让它们可互相替换
场景:不同排序算法、支付方式、压缩算法
#include <iostream>
#include <memory>
#include <functional>
#include <vector>
#include <algorithm>
#include <numeric>
// C++17: 使用function的策略
class Context {
public:
using Strategy = std::function<int(const std::vector<int>&)>;
void setStrategy(Strategy s) { strategy_ = s; }
int execute(const std::vector<int>& data) {
return strategy_ ? strategy_(data) : 0;
}
private:
Strategy strategy_;
};
// 具体策略
int sumStrategy(const std::vector<int>& data) {
return std::accumulate(data.begin(), data.end(), 0);
}
int maxStrategy(const std::vector<int>& data) {
return *std::max_element(data.begin(), data.end());
}
// C++17: if constexpr的编译期策略
template<typename Strategy>
int process(const std::vector<int>& data) {
if constexpr (std::is_same_v<Strategy, struct SumPolicy>) {
return std::accumulate(data.begin(), data.end(), 0);
} else if constexpr (std::is_same_v<Strategy, struct MaxPolicy>) {
return *std::max_element(data.begin(), data.end());
}
return 0;
}
struct SumPolicy {};
struct MaxPolicy {};
int main() {
Context ctx;
std::vector<int> data = {1, 2, 3, 4, 5};
// 运行时策略
ctx.setStrategy(sumStrategy);
std::cout << "Sum: " << ctx.execute(data) << "\n";
ctx.setStrategy(maxStrategy);
std::cout << "Max: " << ctx.execute(data) << "\n";
// Lambda策略
ctx.setStrategy([](const std::vector<int>& d) {
return static_cast<int>(d.size());
});
std::cout << "Count: " << ctx.execute(data) << "\n";
// 编译期策略
std::cout << "Compile sum: " << process<SumPolicy>(data) << "\n";
return 0;
}
22. 模板方法模式 (Template Method)
意图:定义算法骨架,子类重新定义步骤
场景:算法框架、数据处理流程
#include <iostream>
#include <string>
// 传统实现
class AbstractClass {
public:
void templateMethod() {
step1();
step2();
hook();
step3();
}
virtual ~AbstractClass() = default;
protected:
void step1() { std::cout << "Default step1\n"; }
virtual void step2() = 0;
virtual void step3() = 0;
virtual void hook() {} // 可选步骤
};
class ConcreteClass : public AbstractClass {
protected:
void step2() override { std::cout << "Concrete step2\n"; }
void step3() override { std::cout << "Concrete step3\n"; }
void hook() override { std::cout << "Concrete hook\n"; }
};
// C++17: CRTP编译期多态
template<typename Derived>
class CRTPBase {
public:
void algorithm() {
static_cast<Derived*>(this)->step1();
static_cast<Derived*>(this)->step2();
}
protected:
void defaultStep() { std::cout << "Default\n"; }
};
class Derived : public CRTPBase<Derived> {
public:
void step1() { std::cout << "Derived step1\n"; }
void step2() { std::cout << "Derived step2\n"; }
};
int main() {
// 传统版本
std::unique_ptr<AbstractClass> obj = std::make_unique<ConcreteClass>();
obj->templateMethod();
std::cout << "---\n";
// CRTP版本
CRTPBase<Derived> crtp;
crtp.algorithm();
return 0;
}
23. 访问者模式 (Visitor)
意图:在不改变类的前提下定义新操作
场景:编译器AST遍历、文档导出、报表生成
#include <iostream>
#include <variant>
#include <vector>
#include <memory>
// C++17: 使用variant替代双重分发
struct Circle { double radius; };
struct Rectangle { double w, h; };
struct Triangle { double a, b, c; };
using Shape = std::variant<Circle, Rectangle, Triangle>;
// 访问者:面积计算
class AreaVisitor {
public:
double operator()(const Circle& c) const {
return 3.14159 * c.radius * c.radius;
}
double operator()(const Rectangle& r) const {
return r.w * r.h;
}
double operator()(const Triangle& t) const {
// 海伦公式简化版
return 0.5 * t.a * t.b;
}
};
// 访问者:绘制
class DrawVisitor {
public:
void operator()(const Circle&) const { std::cout << "Draw Circle\n"; }
void operator()(const Rectangle&) const { std::cout << "Draw Rectangle\n"; }
void operator()(const Triangle&) const { std::cout << "Draw Triangle\n"; }
};
// 使用访问者
void processShapes(const std::vector<Shape>& shapes) {
AreaVisitor area;
DrawVisitor draw;
for (const auto& shape : shapes) {
std::visit(draw, shape);
double a = std::visit(area, shape);
std::cout << "Area: " << a << "\n\n";
}
}
// C++17: if constexpr的泛型访问
template<typename Visitor, typename... Shapes>
void visitAll(Visitor&& vis, Shapes&&... shapes) {
(std::visit(std::forward<Visitor>(vis), std::forward<Shapes>(shapes)), ...);
}
int main() {
std::vector<Shape> shapes;
shapes.emplace_back(Circle{5.0});
shapes.emplace_back(Rectangle{4.0, 6.0});
shapes.emplace_back(Triangle{3.0, 4.0, 5.0});
processShapes(shapes);
return 0;
}
编译运行
所有代码使用以下命令编译:
g++ -std=c++17 -o pattern pattern.cpp
推荐: GCC 7+ 或 Clang 5+
版本: 3.0 | 纯 C++17 实现 | 全部23种模式完整代码