如何使用智能指针实现构建器设计模式?

问题描述 投票:0回答:1

我想在 C++ 中为我正在从事的项目实现构建器模式。我发现了很多这种使用原始指针的设计模式的例子,但没有一个使用智能指针。由于我的观点是智能指针是编写现代 C++ 代码的方式,我想知道如何通过使用智能指针来实现构建器模式,用于 director、builder、product 等等。

我使用 Refactoring.Guru 的概念示例代码作为 C++ 构建器设计模式的参考:https://refactoring.guru/design-patterns/builder/cpp/example.

如何使用智能指针将这个概念性示例转换为现代 C++ 构建器模式?我知道在存在原始指针的地方,您可以用智能指针替换它们,但我主要是在为在哪里使用唯一指针和共享指针以及如何将它们从一个函数传递到另一个函数而苦苦挣扎。我是使用唯一指针并在每个函数调用中移动它们,还是在产品的情况下使用共享指针?

重构很遗憾。Guru 不包含此示例的此类版本。

提前致谢。

c++ design-patterns smart-pointers builder-pattern
1个回答
0
投票

这里有智能指针:

#include <iostream>
#include <memory>
#include <string>

class Product {
public:
    void set_part_a(std::string const& part_a) {
        part_a_ = part_a;
    }

    void set_part_b(std::string const& part_b) {
        part_b_ = part_b;
    }

    void set_part_c(std::string const& part_c) {
        part_c_ = part_c;
    }

    void show() const {
        std::cout << "Part A: " << part_a_ << "\n";
        std::cout << "Part B: " << part_b_ << "\n";
        std::cout << "Part C: " << part_c_ << "\n";
    }

private:
    std::string part_a_;
    std::string part_b_;
    std::string part_c_;
};

class Builder {
public:
    virtual ~Builder() = default;

    virtual void build_part_a() = 0;
    virtual void build_part_b() = 0;
    virtual void build_part_c() = 0;
    virtual std::unique_ptr<Product> get_product() = 0;
};

class ConcreteBuilder: public Builder {
public:
    ConcreteBuilder(): product_{std::make_unique<Product>()} {}

    void build_part_a() override {
        product_->set_part_a("Part A");
    }

    void build_part_b() override {
        product_->set_part_b("Part B");
    }

    void build_part_c() override {
        product_->set_part_c("Part C");
    }

    std::unique_ptr<Product> get_product() override {
        return std::move(product_);
    }

private:
    std::unique_ptr<Product> product_;
};

class Director {
public:
    void set_builder(std::shared_ptr<Builder> const& builder) {
        builder_ = builder;
    }

    void construct() {
        builder_->build_part_a();
        builder_->build_part_b();
        builder_->build_part_c();
    }

private:
    std::shared_ptr<Builder> builder_;
};

int main() {
    std::shared_ptr<ConcreteBuilder> builder = std::make_shared<ConcreteBuilder>();
    std::shared_ptr<Director> director = std::make_shared<Director>();

    director->set_builder(builder);
    director->construct();

    std::unique_ptr<Product> product = builder->get_product();
    product->show();

    return 0;
}

这是一个非常通用的例子:

#include <iostream>
#include <memory>
#include <string>

template <typename PartA, typename PartB, typename PartC>
class Product {
public:
    void set_part_a(PartA const& part_a) {
        part_a_ = part_a;
    }

    void set_part_b(PartB const& part_b) {
        part_b_ = part_b;
    }

    void set_part_c(PartC const& part_c) {
        part_c_ = part_c;
    }

    void show() const {
        std::cout << "Part A: " << part_a_ << "\n";
        std::cout << "Part B: " << part_b_ << "\n";
        std::cout << "Part C: " << part_c_ << "\n";
    }

private:
    PartA part_a_;
    PartB part_b_;
    PartC part_c_;
};

template <typename PartA, typename PartB, typename PartC>
class Builder {
public:
    virtual ~Builder() = default;

    virtual void build_part_a(PartA const&) = 0;
    virtual void build_part_b(PartB const&) = 0;
    virtual void build_part_c(PartC const&) = 0;
    virtual std::unique_ptr<Product<PartA, PartB, PartC>> get_product() = 0;
};

template <typename PartA, typename PartB, typename PartC>
class ConcreteBuilder: public Builder<PartA, PartB, PartC> {
public:
    void build_part_a(PartA const& part_a) override {
        product_.set_part_a(part_a);
    }

    void build_part_b(PartB const& part_b) override {
        product_.set_part_b(part_b);
    }

    void build_part_c(PartC const& part_c) override {
        product_.set_part_c(part_c);
    }

    std::unique_ptr<Product<PartA, PartB, PartC>> get_product() override {
        return std::make_unique<Product<PartA, PartB, PartC>>(product_);
    }

private:
    Product<PartA, PartB, PartC> product_;
};

template <typename PartA, typename PartB, typename PartC>
class Director {
public:
    void set_builder(std::shared_ptr<Builder<PartA, PartB, PartC>> const& builder) {
        builder_ = builder;
    }

    void construct(PartA const& part_a, PartB const& part_b, PartC const& part_c) {
        builder_->build_part_a(part_a);
        builder_->build_part_b(part_b);
        builder_->build_part_c(part_c);
    }

private:
    std::shared_ptr<Builder<PartA, PartB, PartC>> builder_;
};

int main() {
    std::shared_ptr<ConcreteBuilder<std::string, int, double>> builder = std::make_shared<ConcreteBuilder<std::string, int, double>>();
    std::shared_ptr<Director<std::string, int, double>> director = std::make_shared<Director<std::string, int, double>>();

    director->set_builder(builder);
    director->construct("AAA", 42, 3.14);

    std::unique_ptr<Product<std::string, int, double>> product = builder->get_product();
    product->show();

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.