好了,七月的第一篇博客正式标志着我的回归。六月已经过去,七月还是新的!
GOF的书真的不好懂,不知道是我的原因还是我的原因?好吧,既然不懂只能参考csdn博客了:http://blog.csdn.net/u010064842/article/details/9150921
简单抽象工厂模式
意图:提供一个接口用来创建一系列相关或者相互依赖的对象,而无需指定它们具体的类。
设计模式的学习一定要配合例子。比如说我吃厨师做的食物这件事。食物有很多种,可能是红烧肉,可能是清蒸鱼,每一种特定的食物都是一个具体的类。但是我不需要指定具体的类,我只需要指定一个接口——食物,其中包含了每个具体的食物类的共同的fuction。然后我只要指定厨师类帮我做特定食物类表示的食物就行了。
例子见图:
其实在上图中,厨师就是Factory,食物就是Product。抽象为抽象工厂模式见图:
代码实现:
//产品基类
#ifndef _PRODUCT_H
#define _PRODUCT_H
class Product
{
protected:
Product(){}
public:
virtual ~Product(){}
virtual void function() = 0;
};
#endif
//具体产品A
#ifndef _CONCRETE_PRODUCT_A_H
#define _CONCRETE_PRODUCT_A_H
#include "Product.h"
#include <iostream>
using namespace std;
class ConcreteProductA:public Product
{
public:
ConcreteProductA()
{
cout<<"创建产品A"<<endl;
}
virtual ~ConcreteProductA()
{
cout<<"释放产品A"<<endl;
}
virtual void function()
{
cout<<"这是产品A的基本功能"<<endl;
}
};
#endif
//具体产品B
#ifndef _CONCRETE_PRODUCT_B_H
#define _CONCRETE_PRODUCT_B_H
#include "Product.h"
#include <iostream>
using namespace std;
class ConcreteProductB:public Product
{
public:
ConcreteProductB()
{
cout<<"创建产品B"<<endl;
}
virtual ~ConcreteProductB()
{
cout<<"释放产品B"<<endl;
}
virtual void function()
{
cout<<"这是产品B的基本功能"<<endl;
}
};
#endif
//工厂类:负责具体产品的创建,有两种方式实现产品的创建,
//I、创建不同的产品用不同的方法;II、创建不同产品用相同
//的方法,然后通过传递参数实现不同产品的创建。本实例中
//两种模式都给出了,大家自行分析。
#ifndef _SIMPLE_FACTORY_H
#define _SIMPLE_FACTORY_H
#include "Product.h"
#include "ConcreteProductA.h"
#include "ConcreteProductB.h"
class SimpleFactory
{
public:
SimpleFactory(){}
~SimpleFactory(){}
Product *CreateProduct(int type)
{
Product *p = NULL;
switch(type)
{
case 0:
p = new ConcreteProductA();
break;
case 1:
p = new ConcreteProductB();
break;
default:
p = new ConcreteProductA();
break;
}
return p;
}
Product *CreateProductA()
{
Product *p = new ConcreteProductA();
return p;
}
Product *CreateProductB()
{
Product *p = new ConcreteProductB();
return p;
}
};
#endif
//客户端程序
#include <iostream>
#include "SimpleFactory.h"
#include "Product.h"
using namespace std;
int main(int argc, char **argv)
{
SimpleFactory sf;
Product *p = sf.CreateProductA();
p->function();
delete p;
p = sf.CreateProduct(1);
p->function();
delete p;
system("pause");
return 0;
}
抽象工厂优点:将客户与类相分离,客户通过抽象接口操纵实例,产品的类名也在具体工厂的实现中被分离,不出现在客户代码中。
抽象工厂缺点:对修改不封闭,新增加产品您要修改工厂。违法了鼎鼎大名的开闭法则(OCP)。
抽象工厂模式的改进
在上面的代码中,如果新出来一个ProductC,那我首先需要创建一个ConcreteProductC类,然后在SimpleFactory类中增加对ConcreteProductC的调用,这需要修改SimpleFactory类,使得这个类不能封闭。
改进方法:将厨师类抽象为一个基类,再增加“做红烧肉的厨师类”,“做清蒸鱼的厨师类”等等,它们分别都继承厨师这个基类。现在来看这个模式发生了变化,结构中多了一个厨师的抽象,抽象并不具体的加工产品了,至于是炖汤还是炖鱼,是由这个抽象工厂的继承子类来实现,现在的模式也就变成工厂方法模式了。这样,如果我新出来一个菜,我不需要修改抽象的厨师类或者其他子类,我只需要增加一个做新菜的厨师类,继承于抽象的厨师类,就可以方便的增加一个菜了。
图示:
代码实现:
在原来的基础上增加:
//抽象的工厂类
#ifndef _FACTORY_H
#define _FACTORY_H
#include "Product.h"
class Factory
{
public:
Factory(){}
virtual ~Factory(){}
virtual Product* CreateProduct(int type=0) = 0;
};
#endif
//具体工厂类:工厂基类的具体实现,由此类决定创建具体产品。
//这里ConcreteFactoryA 对于与图中的工厂实现,ConcreteFactoryB
//对于与图中的新工厂。
#ifndef _CONCRETE_FACTORY_A_H
#define _CONCRETE_FACTORY_A_H
#include "Factory.h"
class ConcreteFactoryA: public Factory
{
public:
ConcreteFactoryA(){}
virtual ~ConcreteFactoryA(){}
Product *CreateProduct(int type)
{
Product *p = NULL;
switch (type)
{
case 0:
p = new ConcreteProductA();
break;
case 1:
p = new ConcreteProductB();
break;
default:
p = new ConcreteProductA();
break;
}
return p;
}
};
#endif
//客户端程序
#include <iostream>
#include "SimpleFactory.h"
#include "Product.h"
#include "Factory.h"
#include "ConcreteFactoryA.h"
#include "ConcreteFactoryB.h"
using namespace std;
int main(int argc, char **argv)
{
Factory *f = new ConcreteFactoryA();
Product *p = f->CreateProduct(0);
p->function();
delete p;
p = f->CreateProduct(1);
p->function();
delete p;
delete f;
f = new ConcreteFactoryB();
p = f->CreateProduct();
p->function();
delete p;
delete f;
system("pause");
return 0;
}
当然还可以继续改进,不多说了,见图: