编译运行:clang++ -std=c++26 -Wall -Wextra -pthread 测试_第25章_设计模式.cpp -o t && ./t(需先 cd 测试/)
// 第25章测试:设计模式
#include <print>
#include <memory>
#include <string>
#include <string_view>
#include <vector>
#include <variant>
#include <functional>
#include <chrono>
#include <cmath>
#include <algorithm>
int failures = 0;
#define CHECK(expr) \
do { \
if (!(expr)) { \
++failures; \
std::println("FAIL 第{}行: {}", __LINE__, #expr); \
} \
} while (0)
// 25.2 工厂模式
class Shape {
public:
virtual double area() const = 0;
virtual ~Shape() = default;
};
class Circle : public Shape {
public:
explicit Circle(double r) : r_(r) {}
double area() const override { return 3.14159 * r_ * r_; }
private:
double r_;
};
class Rect : public Shape {
public:
Rect(double w, double h) : w_(w), h_(h) {}
double area() const override { return w_ * h_; }
private:
double w_, h_;
};
enum class ShapeKind { Circle, Rect };
std::unique_ptr<Shape> make_shape(ShapeKind kind, double a, double b) {
switch (kind) {
case ShapeKind::Circle: return std::make_unique<Circle>(a);
case ShapeKind::Rect: return std::make_unique<Rect>(a, b);
}
throw std::runtime_error("未知图形");
}
// 25.3 Meyers 单例
class Logger {
public:
static Logger& instance() {
static Logger log;
return log;
}
void log(std::string_view msg) { std::println("[日志] {}", msg); }
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
private:
Logger() = default;
};
// 25.4 观察者(事件总线)
class EventBus {
public:
using Handler = std::function<void(int)>;
void subscribe(Handler h) { handlers_.push_back(std::move(h)); }
int publish(int event) {
int notified = 0;
for (auto& h : handlers_) { h(event); ++notified; }
return notified;
}
private:
std::vector<Handler> handlers_;
};
// 25.5 RAII 守卫(计时)
class TimerGuard {
public:
explicit TimerGuard(const char* name)
: name_(name), start_(std::chrono::steady_clock::now()) {}
~TimerGuard() {
double ms = std::chrono::duration<double, std::milli>(
std::chrono::steady_clock::now() - start_).count();
std::println("{}: {:.2f} ms", name_, ms);
}
private:
const char* name_;
std::chrono::steady_clock::time_point start_;
};
// 25.7 CRTP
template <typename Derived>
class Base {
public:
void interface() { static_cast<Derived*>(this)->impl(); }
int interface_value() { return static_cast<Derived*>(this)->value_impl(); }
};
class Foo : public Base<Foo> {
public:
void impl() { called_ = true; }
int value_impl() { return 42; }
bool called() const { return called_; }
private:
bool called_ = false;
};
class Bar : public Base<Bar> {
public:
void impl() {}
int value_impl() { return 7; }
};
// 25.8 variant 替代继承
struct VCircle { double r; };
struct VRect { double w, h; };
using VShape = std::variant<VCircle, VRect>;
double varea(const VShape& s) {
return std::visit([](const auto& sh) {
using T = std::decay_t<decltype(sh)>;
if constexpr (std::is_same_v<T, VCircle>)
return 3.14159 * sh.r * sh.r;
else
return sh.w * sh.h;
}, s);
}
// 25.9 依赖注入(可测试性演示)
class DB { public: virtual std::string read() { return "真实数据"; } };
class MockDB : public DB { public: std::string read() override { return "模拟数据"; } };
class Service {
public:
explicit Service(DB& db) : db_(db) {}
std::string fetch() { return db_.read(); }
private:
DB& db_;
};
int main() {
// 25.2 工厂
std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(make_shape(ShapeKind::Circle, 2.0, 0.0));
shapes.push_back(make_shape(ShapeKind::Rect, 3.0, 4.0));
double total = 0;
for (const auto& s : shapes) total += s->area();
CHECK(std::abs(total - (3.14159 * 4.0 + 12.0)) < 1e-3);
// 25.3 单例:两次取到同一实例
CHECK(&Logger::instance() == &Logger::instance());
// 25.4 观察者
EventBus bus;
int received1 = 0, received2 = 0;
bus.subscribe([&](int e) { received1 = e; });
bus.subscribe([&](int e) { received2 = e; });
CHECK(bus.publish(42) == 2);
CHECK(received1 == 42 && received2 == 42);
// 25.5 RAII 守卫
{
TimerGuard t("模拟工作");
volatile long long s = 0;
for (int i = 0; i < 1'000'000; ++i) s += i;
} // 析构时打印
// 25.7 CRTP
Foo f;
Bar b;
f.interface();
CHECK(f.called());
CHECK(f.interface_value() == 42);
CHECK(b.interface_value() == 7);
// 25.8 variant
VShape s1 = VCircle{2.0};
VShape s2 = VRect{3.0, 4.0};
CHECK(std::abs(varea(s1) - 3.14159 * 4.0) < 1e-3);
CHECK(varea(s2) == 12.0);
// 25.9 依赖注入
MockDB mock;
Service svc(mock);
CHECK(svc.fetch() == "模拟数据"); // 测试环境替换成功
if (failures == 0) std::println("全部通过");
return failures;
}