工厂模式

Posted doulcl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了工厂模式相关的知识,希望对你有一定的参考价值。

简单工厂模式:

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();
}

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



























































































































































































































































以上是关于工厂模式的主要内容,如果未能解决你的问题,请参考以下文章

工厂模式抽象工厂模式策略模式

JAVA设计模式——工厂模式简单工厂模式工厂方法模式抽象工厂模式

C++实现工厂模式(简单工厂模式工厂方法模式抽象工厂模式)

设计模式之工厂模式详解和应用

iOS经常使用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)

设计模式——抽象工厂模式