3.1 抽象工厂

来源:互联网 发布:淘宝上怎样交话费 编辑:程序博客网 时间:2024/05/17 05:09

好了,七月的第一篇博客正式标志着我的回归。六月已经过去,七月还是新的!

GOF的书真的不好懂,不知道是我的原因还是我的原因?好吧,既然不懂只能参考csdn博客了:http://blog.csdn.net/u010064842/article/details/9150921

 

简单抽象工厂模式

意图:提供一个接口用来创建一系列相关或者相互依赖的对象,而无需指定它们具体的类。

 

设计模式的学习一定要配合例子。比如说我吃厨师做的食物这件事。食物有很多种,可能是红烧肉,可能是清蒸鱼,每一种特定的食物都是一个具体的类。但是我不需要指定具体的类,我只需要指定一个接口——食物,其中包含了每个具体的食物类的共同的fuction。然后我只要指定厨师类帮我做特定食物类表示的食物就行了。

例子见图:


其实在上图中,厨师就是Factory,食物就是Product。抽象为抽象工厂模式见图:


代码实现://产品基类#ifndef _PRODUCT_H#define _PRODUCT_Hclass 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;}

当然还可以继续改进,不多说了,见图:



原创粉丝点击