【问题标题】:difference in structure of abstract factory抽象工厂的结构差异
【发布时间】:2020-03-19 19:07:45
【问题描述】:

我为抽象工厂编写了两种类型的代码:type1 和 type2
type1 是我通过互联网上的网站得出的
但我认为 type2 应该是一个更好的约定

类型1
首先是所需最终产品的基类。需要工厂的基类。决定需要什么品牌的工厂。通过派生实例化它们的具体类。确定每个品牌的工厂应该提供哪些常见类别。然后通过推导实例化每个最终产品的最终产品的具体。但是在 main function 中,您是直接创建工厂对象。这样的代码将需要更多的维护。

  class Shoe
    {
    public:
        virtual void Detail() = 0;
    char make[2];
    int size;
    };

    class Shoe_B5:public Shoe //small
    {
    public:
        Shoe_B5()
        {
            strcpy(make,"B");
            size = 5;
        }
        void Detail()
        {
            cout<<"Shoe"<<make<<size<<endl;
        }
    };

    class Shoe_B6:public Shoe //medium
    {
    public:
        Shoe_B6()
        {
            strcpy(make,"B");
            size = 6;
        }
        void Detail()
        {
            cout<<"Shoe"<<make<<size<<endl;
        }

    };

    class Shoe_B7:public Shoe //large
    {
    public:
        Shoe_B7()
        {
            strcpy(make,"B");
            size = 7;
        }
        void Detail()
        {
            cout<<"Shoe"<<make<<size<<endl;
        }

    };

    class Shoe_B8:public Shoe //XL
    {
    public:
        Shoe_B8()
        {
            strcpy(make,"B");
            size = 8;
        }
        void Detail()
        {
            cout<<"Shoe"<<make<<size<<endl;
        }

    };

    class Shoe_RT5:public Shoe //small
    {
    public:
        Shoe_RT5()
        {
            strcpy(make,"RT");
            size = 5;
        }
        void Detail()
        {
            cout<<"Shoe"<<make<<size<<endl;
        }

    };


    class Shoe_RT6:public Shoe //medium
    {
    public:
        Shoe_RT6()
        {
            strcpy(make,"RT");
            size = 6;
        }
        void Detail()
        {
            cout<<"Shoe"<<make<<size<<endl;
        }

    };

    class Shoe_RT7:public Shoe //Large
    {
    public:
        Shoe_RT7()
        {
            strcpy(make,"RT");
            size = 7;
        }
        void Detail()
        {
            cout<<"Shoe"<<make<<size<<endl;
        }

    };


    class Shoe_RT8:public Shoe //XL
    {
    public:
        Shoe_RT8()
        {
            strcpy(make,"RT");
            size = 8;
        }
        void Detail()
        {
            cout<<"Shoe"<<make<<size<<endl;
        }

    };

    class Factory
    {
    public:
        virtual Shoe* createSmall() = 0;
        virtual Shoe* createMedium() = 0;
        virtual Shoe* createLarge() = 0;
        virtual Shoe* createXL() = 0;
    };

    class BataFactory: public Factory
    {
    public:
        Shoe* createSmall()
        {
            return new Shoe_B5;
        }
        Shoe* createMedium()
        {

            return new Shoe_B6;
        }
        Shoe* createLarge()
        {

            return new Shoe_B7;
        }
        Shoe* createXL()
        {

            return new Shoe_B8;
        }
    };


    class RedTapeFactory: public Factory
    {
    public:
        Shoe* createSmall()
        {

            return new Shoe_RT5;
        }
        Shoe* createMedium()
        {

            return new Shoe_RT6;
        }
        Shoe* createLarge()
        {

            return new Shoe_RT7;
        }
        Shoe* createXL()
        {

            return new Shoe_RT8;
        }
    };

    class Client
    {
    Factory* fac;
    Shoe* s;
    public:
        Client(Factory* factory)
        {
            fac = factory;
        }
        Shoe* Create(int num)
        {
            switch(num)
            {
                case 1:
                      s = fac->createSmall();
                      break;

                case 2:
                      s = fac->createMedium();
                      break;

                case 3:
                      s = fac->createLarge();
                      break;

                case 4:
                      s = fac->createXL();
                      break;

            }
        }
        void getDetails()
        {
            s->Detail();
        }

    };

int main()
{
    Factory * fac;
    if(condition)
        fac = new BataFactory;
    else
        fac = new RedTapeFactory;

    Client * c = new Client(fac);
    c->create(Size);
    c->getDetails();
}

类型 2 的差异
但是在 main 函数中,您正在像在工厂方法中一样创建工厂。这样的代码需要更少的维护。

 class Factory
    {
    public:
        //produce allowed category of shoes
        virtual Shoe* createSmall() = 0;
        virtual Shoe* createMedium() = 0;
        virtual Shoe* createLarge() = 0;
        virtual Shoe* createXL() = 0;
        //produce allowed category of factories
        static Factory* CreateFactory(int num);

    };

    Factory* Factory::CreateFactory(int num)
        {
            switch(num)
            {
                case 1:
                    return new BataFactory;
                    break;
                case 2:
                    return new RedTapeFactory;
                    break;
            }
        }

int main()
{
    Factory * fac;
    switch(condition)
        {
             case 1:
                   fac = Factory::CreateFactory(1);
                   break;
             case 2:
                   fac = Factory::CreateFactory(2);
                   break;

        }
    Client * c = new Client(fac);
    c->create(Size);
    c->getDetails();
}

【问题讨论】:

    标签: c++


    【解决方案1】:

    嗯,您正在使用 new 和原始指针来获取拥有的内存。这不应该在 C++ 中完成。它总是会产生问题。

    例如,在您的代码中,您永远不会删除此内存。这将导致内存泄漏。所以,请不要使用new 和原始指针来拥有内存。以后使用`````std::unique_ptr`` 或类似的。

    我还看到案例陈述。这也不是现代工厂变体的常用方法。你应该使用std::map,选择器作为键,函数指针作为值。

    如果您允许使用可变参数模板构造具有不同数量参数的类,则可以增加一点灵活性。

    请在此处查看(众多)工厂实施的可能解决方案。

    `#include <iostream>
    #include <map>
    #include <utility>
    #include <any>
    
    
    // Some demo classes ----------------------------------------------------------------------------------
    struct Base {
        Base(int d) : data(d) {};
        virtual ~Base() { std::cout << "Destructor Base\n"; }
        virtual void print() { std::cout << "Print Base\n"; }
        int data{};
    };
    struct Child1 : public Base {
        Child1(int d, std::string s) : Base(d) { std::cout << "Constructor Child1 " << d << " " << s << "\n"; }
        virtual ~Child1() { std::cout << "Destructor Child1\n"; }
        virtual void print() { std::cout << "Print Child1: " << data << "\n"; }
    };
    struct Child2 : public Base {
        Child2(int d, char c, long l) : Base(d) { std::cout << "Constructor Child2 " << d << " " << c << " " << l << "\n"; }
        virtual ~Child2() { std::cout << "Destructor Child2\n"; }
        virtual void print() { std::cout << "Print Child2: " << data << "\n"; }
    };
    struct Child3 : public Base {
        Child3(int d, long l, char c, std::string s) : Base(d) { std::cout << "Constructor Child3 " << d << " " << l << " " << c << " " << s << "\n"; }
        virtual ~Child3() { std::cout << "Destructor Child3\n"; }
        virtual void print() { std::cout << "Print Child3: " << data << "\n"; }
    };
    
    
    
    using UPTRB = std::unique_ptr<Base>;
    
    
    template <class Child, typename ...Args>
    UPTRB createClass(Args...args) { return std::make_unique<Child>(args...); }
    
    // The Factory ----------------------------------------------------------------------------------------
    template <class Key, class Object>
    class Factory
    {
        std::map<Key, std::any> selector;
    public:
        Factory() : selector() {}
        Factory(std::initializer_list<std::pair<const Key, std::any>> il) : selector(il) {}
    
        template<typename Function>
        void add(Key key, Function&& someFunction) { selector[key] = std::any(someFunction); };
    
        template <typename ... Args>
        Object create(Key key, Args ... args) {
            if (selector.find(key) != selector.end()) {
                return std::any_cast<std::add_pointer_t<Object(Args ...)>>(selector[key])(args...);
            }
            else return nullptr;
        }
    };
    
    int main()
    {
        // Define the factory with an initializer list
        Factory<int, UPTRB> factory{
            {1, createClass<Child1, int, std::string>},
            {2, createClass<Child2, int, char, long>}
        };
    
        // Add a new entry for the factory
        factory.add(3, createClass<Child3, int, long, char, std::string>);
    
    
        // Some test values
        std::string s1(" Hello1 "); std::string s3(" Hello3 ");
        int i = 1;  const int ci = 1;   int& ri = i;    const int& cri = i;   int&& rri = 1;
    
        UPTRB b1 = factory.create(1, 1, s1);
        UPTRB b2 = factory.create(2, 2, '2', 2L);
        UPTRB b3 = factory.create(3, 3, 3L, '3', s3);
    
        b1->print();
        b2->print();
        b3->print();
        b1 = factory.create(2, 4, '4', 4L);
        b1->print();
        return 0;
    }
    

    【讨论】:

    • 1 个问题,我什么都懂,但是什么是 int data{};在 struct base 的末尾?
    • 你能不能也看看下面的-> stackoverflow.com/questions/59017834/…
    • 我看过int数据;整数数据(0);但从未见过 int 数据{}
    • 为什么我们从 factory.create() 返回 UPTRB 对象;我认为我们应该将它存储在地图的某个地方;我们可以在工厂中有一个访问器方法,它获取密钥并返回 UPTRB 对象
    猜你喜欢
    • 1970-01-01
    • 2011-01-05
    • 1970-01-01
    • 1970-01-01
    • 2014-01-14
    • 1970-01-01
    • 2013-10-17
    • 2011-09-08
    • 1970-01-01
    相关资源
    最近更新 更多