Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 工厂模式中的传递值_C++_Design Patterns_Factory Pattern - Fatal编程技术网

C++ 工厂模式中的传递值

C++ 工厂模式中的传递值,c++,design-patterns,factory-pattern,C++,Design Patterns,Factory Pattern,我正在学习工厂设计模式。我不知道如何将参数传递给使用Factory模式创建的对象 一个愚蠢的小例子: 假设我有三个类,class A和class B和classNumber编号是基类。此外,类A需要三个整数并具有相加功能,而类B需要两个整数并相加 代码段: int main() { Factory *facObj = new Factory(); // Addition for Two Integers Number * numberObjOne = facObj-&g

我正在学习工厂设计模式。我不知道如何将参数传递给使用Factory模式创建的对象

一个愚蠢的小例子:

假设我有三个类,
class A
class B
和class
Number
<代码>编号是
基类
。此外,类A需要三个整数并具有相加功能,而类B需要两个整数并相加

代码段:

int main()
{

    Factory *facObj = new Factory();
    // Addition for Two Integers
    Number * numberObjOne = facObj->createObj("AddThreeInteger");
    Number * numberObjTwo = facObj->createObj("AddTwoInteger");
}
Factory.cpp

Number * Factory::createObj(string str)
{
    if (str == "AddThreeInteger")
    {
        return new A(1,2,3);
    }
    else if (str == "AddTwoInteger")
    {
        return new B(1,2);
    }
    else            
        return NULL;
}

问题:现在无论我做什么,我只能添加硬编码的数字。如何从客户端代码或main()传递这些整数值。这是一个愚蠢的例子,我是编程新手。请帮帮我。我如何才能不硬编码值并获得结果。我可以在
facObj->createObj
传递值吗?请帮帮我。

我不是设计模式方面的专家。因此,我不确定以下建议是否仍然符合工厂模式


一种方法是创建不同的方法,如
CreateObjectA(inta,intb,intc)
CreateObjectB(inta,intb)
。另一个选项是向方法
createObj
添加
std::vector
。如果所有A、B类。。。不同的整数数量,向量的长度可以用来决定创建哪个对象。如果这是不可能的,例如,您可以使用某种ID告诉工厂要创建哪个对象。

有很多方法

一种方法是在工厂中使用单独的create方法来构造每个子类。每个create方法将为它构造的子类获取适当的参数,并相应地将它们转发给子类的构造函数

另一种方法是使用一个单独的“parameters”类,以某种方式定义所创建对象的参数。它将允许指定这些参数。对于这种情况,一个
std::vector
是合适的。然后,create()方法必须验证传递的参数是否有效,否则抛出异常,或者抛出类似的异常。

选项1 可以使用模板泛化factory类

例如,可以将要构造的类型发送到工厂

这是一个关于您的案例可能的解决方案的示例:

struct Factory {
    template<typename T, typename... Args>
    T create(Args&&... args) {
        return T{1, 2, std::forward<Args>(args)...};
    }
};
您可以这样使用它:

Factory factory;

auto myA = factory.create<A>(1, 2, "an additional char* parameter");

// no additional parameter works too
auto myB = factory.create<B>();
Factory factory;

auto myA = factory.create(1, 2, 3);
auto myB = factory.create(1, 2);

这可能更容易实现。但请注意,您将无法拥有一个具有两个构造函数的类,也无法拥有两个具有相同参数的类。

完整的可运行示例。c++11或更高版本

注意unique_ptr的使用。不要使用原始指针

#include <iostream>
#include <memory>
#include <stdexcept>
#include <exception>
#include <utility>

template<class T, class...Args>
struct creatable_from {
    template<class X, class...Ys>
    static auto test(int) -> decltype(X(std::declval<Ys>()...), void(), std::true_type());

    template<class X, class...Ys>
    static auto test(...) -> decltype(std::false_type());

    static constexpr auto value = decltype(test<T, Args...>(0))::value;

};

struct Operation {
    virtual ~Operation() = default;

    virtual int operator()() const = 0;
};

struct Add : Operation
{
    Add(int x, int y)
    : x(x), y(y)
    {}

    int operator()() const override {
        return x + y;
    }

    int x, y;
};

struct Sub : Operation
{
    Sub(int x, int y)
    : x(x), y(y)
    {}

    int operator()() const override {
        return x - y;
    }

    int x, y;
};

struct AddSub : Operation
{
    AddSub(int x, int y, int z)
    : x(x), y(y), z(z)
    {}

    int operator()() const override {
        return x + y - z;
    }

    int x, y, z;
};

struct Factory
{
    template<class...Args>
    std::unique_ptr<Operation> create(const std::string& type, Args&&...args)
    {
        if (type == "Add") {
            return do_create<Add>(std::forward<Args>(args)...);
        }
        if (type == "Sub") {
            return do_create<Sub>(std::forward<Args>(args)...);
        }
        if (type == "AddSub") {
            return do_create<AddSub>(std::forward<Args>(args)...);
        }

        // default - return a null pointer, but would probably be better to
        // throw a logic_error
        return {};
    }

private:
    template<class T, class...Args>
    static auto do_create(Args&&...args)
    -> std::enable_if_t< creatable_from<T, Args...>::value, std::unique_ptr<T> >
    {
        return std::make_unique<T>(std::forward<Args>(args)...);
    }

    template<class T, class...Args>
    static auto do_create(Args&&...args)
    -> std::enable_if_t< not creatable_from<T, Args...>::value, std::unique_ptr<T> >
    {
        throw std::invalid_argument("wrong number of arguments");
    }

};

int main()
{

    auto facObj = Factory();
    auto t1 = facObj.create("Add", 2, 3);
    auto t2 = facObj.create("Sub", 3, 2);
    auto t3 = facObj.create("AddSub", 2, 3, 4);

    std::cout << (*t1)() << std::endl;
    std::cout << (*t2)() << std::endl;
    std::cout << (*t3)() << std::endl;
}

谢谢你的帮助。请提供一个小代码段。我如何从main()向这些
CreateObjectA
传递值。非常感谢!
#include <iostream>
#include <memory>
#include <stdexcept>
#include <exception>
#include <utility>

template<class T, class...Args>
struct creatable_from {
    template<class X, class...Ys>
    static auto test(int) -> decltype(X(std::declval<Ys>()...), void(), std::true_type());

    template<class X, class...Ys>
    static auto test(...) -> decltype(std::false_type());

    static constexpr auto value = decltype(test<T, Args...>(0))::value;

};

struct Operation {
    virtual ~Operation() = default;

    virtual int operator()() const = 0;
};

struct Add : Operation
{
    Add(int x, int y)
    : x(x), y(y)
    {}

    int operator()() const override {
        return x + y;
    }

    int x, y;
};

struct Sub : Operation
{
    Sub(int x, int y)
    : x(x), y(y)
    {}

    int operator()() const override {
        return x - y;
    }

    int x, y;
};

struct AddSub : Operation
{
    AddSub(int x, int y, int z)
    : x(x), y(y), z(z)
    {}

    int operator()() const override {
        return x + y - z;
    }

    int x, y, z;
};

struct Factory
{
    template<class...Args>
    std::unique_ptr<Operation> create(const std::string& type, Args&&...args)
    {
        if (type == "Add") {
            return do_create<Add>(std::forward<Args>(args)...);
        }
        if (type == "Sub") {
            return do_create<Sub>(std::forward<Args>(args)...);
        }
        if (type == "AddSub") {
            return do_create<AddSub>(std::forward<Args>(args)...);
        }

        // default - return a null pointer, but would probably be better to
        // throw a logic_error
        return {};
    }

private:
    template<class T, class...Args>
    static auto do_create(Args&&...args)
    -> std::enable_if_t< creatable_from<T, Args...>::value, std::unique_ptr<T> >
    {
        return std::make_unique<T>(std::forward<Args>(args)...);
    }

    template<class T, class...Args>
    static auto do_create(Args&&...args)
    -> std::enable_if_t< not creatable_from<T, Args...>::value, std::unique_ptr<T> >
    {
        throw std::invalid_argument("wrong number of arguments");
    }

};

int main()
{

    auto facObj = Factory();
    auto t1 = facObj.create("Add", 2, 3);
    auto t2 = facObj.create("Sub", 3, 2);
    auto t3 = facObj.create("AddSub", 2, 3, 4);

    std::cout << (*t1)() << std::endl;
    std::cout << (*t2)() << std::endl;
    std::cout << (*t3)() << std::endl;
}
5
1
1