测试_第25章_设计模式.cpp

← 测试总览 · 目录

编译运行: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;
}