zoukankan      html  css  js  c++  java
  • 工厂模式

    简单工厂模式:

    typedef enum
    {
        A,
        B
    } productType;
    class product
    {
    public:
        product(){};
        ~product(){};
        virtual void show()=0;
    };
    class productA : public product
    {
    public:
        productA(){};
        ~productA(){};
        void show()
        {
            cout<<"productA"<<endl;
        };
    };
    class productB : public product
    {
    public:
        productB(){};
        ~productB(){};
        void show()
        {
            cout<<"productB"<<endl;
        };
    };
    class Factory
    {
    public:
        Factory(){};
        ~Factory(){};
        product * createProduct(int type)
        {
            product * pl = NULL;
            switch(type)
            {
                case(A):  pl = new productA(); break;
                case(B):  pl = new productB(); break;
                default:
                break;
            }
            return pl;
        }
    };
    void main()
    {
        Factory a;
        a.createProduct(A)->show();
        a.createProduct(B)->show();
        cin.get();
    }

    定义一个工厂,里面生产若干产品,通过swtich(case)输入参数来确定生产那种产品,缺点是可扩展性不强,增加产品时需要修改factory这个类,好的设计模式要求只扩展而不修改。

    写的时候发现报错,原因是我写factory基类时忘了加public,我查了下,未定义权限时,因为类的默认权限都是private,导致子类构造时无法调用到父类的构造函数导致报错

    另外还有临时变量的自动释放问题,为什么我createProduct返回的这个Product的指针可以,不是栈区的应该被释放了么,看下面的例子:

    char* getStr(void)
    {
        //char* p = new char[20];
        char p[] ="hello";
        printf("p:%p ",p);
        return p;
    };
    char* getStr2(void)
    {
        char p1[] ="hello2";
        printf("p1:%p ",p1);
        return p1;
    };
    int* getStr3(void)
    {
        int a = 8;
        int *p =&a;
        printf("p2:%p ",p);
        return p;
    };
    char* getStr4(void)
    {
        char *p1 ="hello2";
        printf("p3:%p ",p1);
        return p1;
    };

    void main()
    {
        char* str1 = getStr();
        char* str2 = getStr2();
        int* str3 = getStr3();
        char* str4 = getStr4();
        printf("%p:%s.. ...%p:%s ",str1,str1,str2,str2);
        printf("%p:%d.. ...%p:%s m",str3,*str3,str4,str4);
        system("pause");
    }

    debug:

    release:

    因此,我们可以这样理解,栈区资源的释放实际是临时指针的释放,不指向这块内存,从而可以使得这块内存被其他的使用。在release中栈内存内内容不发生变化,在debug版本中指针内容销毁(不知道为什么)。而返回值另存到寄存器中,实际是否能得到,还得看变量存储的位置,getStr4()这样写一定能取到值,是因为char p1[] ="hello2";这样定义字符串存储在栈区,随着内存销毁即便得到了这个栈地址,地址内的内容也已经被销毁,而char *p1 ="hello2";这样定义“hello2”存放在常量区,从地址值也可以看出,随着临时指针销毁(无法再获取p,但这个函数能将这个栈内指针转存到其他寄存器中),这个存放在常数区的“hello2”并不会被销毁,事实上这个指针指向堆区地址也能得到取到指针内容(也就是上述我们可以得到product指针内容的原因)。

    工厂方法模式:

    为了不修改factory,于是产生了工厂方法模式,一个工厂只生成一种产品,要再生产另一种时,那么产生一个新的工厂即可。

    typedef enum
    {
        A,
        B
    } productType;
    class product
    {
    public:
        product(){};
        ~product(){};
        virtual void show()=0;
    };
    class productA : public product
    {
    public:
        productA(){};
        ~productA(){};
        void show()
        {
            cout<<"productA"<<endl;
        };
    };
    class productB : public product
    {
    public:
        productB(){};
        ~productB(){};
        void show()
        {
            cout<<"productB"<<endl;
        };
    };
    class Factory
    {
    public:
        Factory(){};
        ~Factory(){};
        virtual product* create()=0;
    };
    class FactoryA:public Factory
    {
    public:
        FactoryA(){};
        ~FactoryA(){};
        product* create()
        {
            return new productA();
        }
    };
    class FactoryB:public Factory
    {
    public:
        FactoryB(){};
        ~FactoryB(){};
        product* create()
        {
            return new productB();
        }
    };
    void main()
    {
        Factory * FA = new FactoryA();
        Factory * FB = new FactoryB();
        FA->create()->show();
        FB->create()->show();
        cin.get();
    }

    上面基本比较简单,涉及c++的多态,用父类指针去管理子类对象,new出来时右边实际是子类指针,为什么子类指针可以转换为父类指针相反却不可以呢,子类对象其实包含父类的内容,所以是一个更大的概念,我们可以这么想,大的转换成小的只需要裁剪即可,而小的转换成大的实际是不可能的。

    那还有强制的需求,需要一个工厂生产多个产品,那只能用第3种工厂模式

    抽象工厂模式:

    实际是第二种的扩展,如下:

    class product
    {
    public:
        product(){};
        ~product(){};
        virtual void show()=0;
    };
    class productA1 : public product
    {
    public:
        productA1(){};
        ~productA1(){};
        void show()
        {
            cout<<"productA1"<<endl;
        };
    };
    class productA2 : public product
    {
    public:
        productA2(){};
        ~productA2(){};
        void show()
        {
            cout<<"productA2"<<endl;
        };
    };
    class productB2 : public product
    {
    public:
        productB2(){};
        ~productB2(){};
        void show()
        {
            cout<<"productB2"<<endl;
        };
    };
    class productB1 : public product
    {
    public:
        productB1(){};
        ~productB1(){};
        void show()
        {
            cout<<"productB1"<<endl;
        };
    };
    class Factory
    {
    public:
        Factory(){};
        ~Factory(){};
        virtual product* create1()=0;
        virtual product* create2()=0;   //若超过2种最开始就做好createN()
    };
    class FactoryA:public Factory
    {
    public:
        FactoryA(){};
        ~FactoryA(){};
        product* create1()
        {
            return new productA1();
        }
        product* create2()
        {
            return new productA2();
        }
    };
    class FactoryB:public Factory
    {
    public:
        FactoryB(){};
        ~FactoryB(){};
        product* create1()
        {
            return new productB1();
        }
        product* create2()
        {
            return new productB2();
        }
    };
    void main()
    {
        Factory * FA = new FactoryA();
        Factory * FB = new FactoryB();
        FA->create1()->show();
        FA->create2()->show();
        FB->create1()->show();
        FB->create2()->show();
        cin.get();
    }

    这些个例子网上也能找到,自己写写练习一下

  • 相关阅读:
    求出123456 8910,数字,显示出来
    Django之Model操作
    AJAX全套
    Python之路【第十六篇】:Django【基础篇】
    Q2Day81
    Django第二重点(thml与django连接)
    react
    es6 和 python 语法比较
    微信
    py库: GUI(tkinter)
  • 原文地址:https://www.cnblogs.com/doulcl/p/10096953.html
Copyright © 2011-2022 走看看