设计模式之抽象工厂模式(Abstract Factory)
来源:互联网 发布:天津网络推广招聘 编辑:程序博客网 时间:2024/05/22 11:55
1.简单实现
简单工厂模式生活例子 吃饭。 如果你想吃饭了,怎么办自己做吗?自己做就相当于程序中直接使用new。当然是自己下个指令,别人来做更爽。那就把做饭的任务交给你的老婆吧,那么她就是 一个做饭的工厂了,你告诉她要要吃红烧肉,等会她就从厨房给你端出来一盘香喷喷的红烧肉了,再来个清蒸鱼吧,大鱼大肉不能太多,那就再来个爆炒空心菜,最 后再来个西红柿鸡蛋汤。下图 1) 就是这个问题的模型。
显然到了这里,你是Client,你老婆就是工厂,她拥有做红烧肉的方法,做清蒸鱼的方法,做爆炒空心菜、西红柿鸡蛋汤的方法,这些方法返回值就是食物 抽象。红烧肉、清蒸鱼、爆炒空心菜、西红柿鸡蛋汤就是食物的继承类,到这里你就可以大吃二喝了。简单工厂模式也成型了。哈哈,娶一个手艺不错的老婆还真 好,吃的好,吃的爽,又清闲。 下面来看标准的简单工厂模式的分析。 意图 把一系列拥有共同特征的产品的创建封装 结构图:
代码实现: //---这时一个系列的产品基类class Product{protected: Product(void){};public: virtual ~Product(void){};public: virtual void Function() = 0;};具体产品类:产品1和产品2,这个角色实现了抽象产品角色所定义的接口。代码实现: //产品Aclass ConcreteProductA:public Product{public: ConcreteProductA(void) {cout<<"创建 A 产品"<<endl; };public: virtual ~ConcreteProductA(void) {cout<<"释放 A 产品"<<endl;}public: virtual void Function(); {cout<<"这是产品 A 具有的基本功能"<<endl;}};//工厂类:负责具体产品的创建,有两种方式实现产品的创建,I、创建不同的产品用不同的方法;II、创建不同产品用相同的方法,然后通过传递参数实现不同产品的创建。本实例中两种模式都给出了,大家自行分析。 class SimpleFactory{public: SimpleFactory(){}public: ~SimpleFactory(){}public: Product *CreateProduct(int ProuctType) { Product *p = 0; switch(ProductType) { case 0: p= new ConcreteProductA(); break; case 1: p= new ConcreteProductB(); break; default: p= new ConcreteProductA(); break; } return p; } Product *CreateProductA() {return new ConcreteProductA();} Product *CreateProductB() {return new ConcreteProductB();}};//客服端程序SimpleFactory sf;Product *p = sf.CreateProductA();p->Function();delete p;p = sf.CreateProductB();p->Function();delete p;
优缺点说明优点:(1) 首先解决了代码中大量New的问题。为何要解决这个问题,好处的说明我想放到结尾总结中。
(2) 用工厂方法在一个类的内部创建对象通常比直接创建对象更灵活。
缺点:对修改不封闭,新增加产品您要修改工厂。违法了鼎鼎大名的开闭法则(OCP)。
2.深入改进
人是最贪得无厌的动物,老婆手艺再好,总有不会做的菜,你想吃回锅肉,怎么办,让老婆学呗,于是就给她就新增了做回锅肉的方法,以后你再想吃一个新菜,就 要给你老婆新加一个方法,显然用老婆做菜的缺点也就暴露出来了,用程序设计的描述就是对修改永远不能封闭。当然优点也是有的,你有了老婆这个工厂,这些菜 不用你自己做了,只要直接调用老婆这个工厂的方法就可以了。
面对上面对修改不能封闭的问题,有没有好的解决方案吗,如果你有钱,问题就迎刃而解了,把老婆抽象变成一个基类,你多娶几个具体的老婆,分别有做鱼 的,做青菜的,炖汤的老婆,如果你想吃一个新菜,就再新找个女人,从你的老婆基类继承一下,让她来做这个新菜。显然多多的老婆这是所有男人的梦想,没有办 法,法律不允许,那么咱们只是为了做饭,老婆这个抽象类咱们不叫老婆了,叫做厨师吧,她的子类也自然而然的该叫做鱼的厨师、炖汤的厨师了。现在来看这个模 式发生了变化,结构中多了一个厨师的抽象,抽象并不具体的加工产品了,至于是炖汤还是炖鱼,是由这个抽象工厂的继承子类来实现,现在的模式也就变成工厂方 法模式了,这个上面的结构图1)就变成了下面的图3的结构了。
现在再来分析现在的模式,显然简单工厂的缺陷解决了,新增加一个菜只需要新增加一个厨师就行了,原来的厨师还在做原来的工作,这样你的设计就对修改封 闭了。你看把老婆解放出来,招聘大量的厨师到你家里这个方案多么的完美,你老婆也会爱死你了。当然前提就是你要有多多的钱噢,当然这里的钱的多少在软件领 域应该看你的客户软件投资方的要求。
下面来一下标准的工厂模式的实现意图。定义一个用户创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。上面是GOF关于此模式的意图描述,我想补充的是您可以这样理解:为了改善简单工厂对修改不能关闭的问题。
结构
//工厂模式,此模式的工厂只定义加工产品的接口,具体生成交予其继承类实现//只有具体的继承类才确定要加工何种产品class Factory{public: Factory(void){};public: virtual ~Factory(void){};public: virtual Product* CreateProduct(int ProductType = 0) =0;};//具体工厂类:工厂基类的具体实现,由此类决定创建具体产品,这里 ConcreteFactory1 对于与图中的 工厂实现,ConcreteFactory2 对于与图中的新工厂。class ConcreteFactory1:public Factory{public: ConcreteFactory1(){};public: virtual ~ConcreteFactory1(){};public : Product* CreateProduct(int ProductType) { Product *p = 0; switch(ProductType) { case 0: p= new ConcreteProductA(); break; case 1: p= new ConcreteProductB(); break; default: p= new ConcreteProductA(); break; } return p; }};class ConcreteFactory2:public Factory{public: ConcreteFactory2(){};public: virtual ~ConcreteFactory2(){};public : Product* CreateProduct(int ProductType) {return new ConcreteProductANew();}};//客户调用Factory*fct = new ConcreteFactory1();Product *p = fct->CreateProduct(0);p->Function();delete p;p = fct->CreateProduct(1);p->Function();delete p;delete fct;fct = new ConcreteFactory2();p=fct->CreateProduct();delete p;delete fct;
缺点:对于创建不同系列的产品无能为力 适用性
- 当一个类不知道它所必须创建的对象的类的时候。
- 当一个类希望由它的子类来指定它所创建的对象的时候。
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
3.继续深入改进
抽象工厂模式生活例子 世事多变,随着时间的推移,走过的地方越来越多,你天南海北的朋友也越来越多。你发现菜原来还分了许多菜系,鲁菜、粤菜、湘菜等等,它们各有各的风味,同 样是红烧肉由不同菜系出来的味道也各不相同, 你招待不同的朋友要用不同的菜系,这下难办了,你的厨师都是鲁菜风味,怎么办,广东的朋友来了吃不惯。现在我们再回到简单工厂模式(就是老婆做菜的模 式),我们把红烧肉再向下继承,生成鲁菜红烧肉、粤菜红烧肉、湘菜红烧肉;清蒸鱼向下继承为鲁菜清蒸鱼、粤菜清蒸鱼、湘菜清蒸鱼,其它也以此类推。我们也 修改一下老婆的这个类,不让其返回食物基类,而是返回红烧肉、清蒸鱼、爆炒空心菜、西红柿鸡蛋汤这一层次,并把这些方法抽象化,作为菜系工厂基类,然后再 从此基类继承出,鲁菜工厂、粤菜工厂、湘菜工厂等等,再由这些具体工厂实现创建具体菜的工作,哈哈你如果招待广东朋友就用粤菜工厂,返回的就是一桌粤菜菜 系的红烧肉、清蒸鱼、空心菜和西红柿鸡蛋汤了,你的广东朋友一定会吃的非常合乎胃口了。噢,非常好,你已经实现了抽象工厂模式了。
现在可以看到,想新来做一个菜系,只需新聘请一个厨师就可以了,多么完美,但是你先别高兴太早,如果你想新增加一个菜就变得非常困难了。
意图 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
//产品Aclass ConcreteProductA:public Product{public: ConcreteProductA(void) {cout<<"创建 A 产品"<<endl;}public: virtual ~ConcreteProductA(void) {cout<<"释放 A 产品"<<endl;}public: virtual void Function() {cout<<"这是产品 A 具有的基本功能"<<endl;}};//产品B与A类似不这里不再给出//下面是具体的产品class ConcreteProductA1:public ConcreteProductA{public:ConcreteProductA1(void){cout<<"创建 A1 产品"<<endl;}public:virtual ~ConcreteProductA1(void){cout<<"释放 A1 产品"<<endl;}public:virtual void Function(){cout<<"这时产品 A1 具有的基本功能"<<endl;}};//抽象工厂class AbstractFactory{public:AbstractFactory(){};public:virtual ~AbstractFactory(){};public:virtual ConcreteProductA* CreateA() = 0;virtual ConcreteProductB* CreateB() = 0;};//具体工厂实现类:工厂1和工厂2。新增加系列,只需新实现一个工厂。class ConcreteAbsFactory1:public AbstractFactory{public:ConcreteAbsFactory1(){};public:virtual ~ConcreteAbsFactory1(){};public:virtual ConcreteProductA* CreateA() {return new ConcreteProductA1();}virtual ConcreteProductB* CreateB(){return new ConcreteProductB1();}};//客户访问代码AbstractFactory *absfct = new ConcreteAbsFactory1();ConcreteProductA *cpa = absfct->CreateA();cpa->Function();delete cpa;ConcreteProductB *cpb = absfct->CreateB();cpb->Function();delete cpb;delete absfct;absfct = new ConcreteAbsFactory2();cpa = absfct->CreateA();cpa->Function();delete cpa;cpb = absfct->CreateB();cpb->Function();delete cpb;
- 【设计模式】之 Abstract Factory 抽象工厂
- 设计模式之:抽象工厂(Abstract Factory)
- 设计模式之抽象工厂Abstract Factory
- 设计模式之抽象工厂Abstract Factory
- 设计模式笔记之工厂模式--抽象工厂(Abstract Factory)
- 设计模式-抽象工厂模式(Abstract Factory)
- 设计模式:抽象工厂模式(Abstract Factory)
- .Net设计模式之抽象工厂模式(Abstract Factory)
- Net设计模式之抽象工厂模式(Abstract Factory Pattern)
- 设计模式(二)之Abstract Factory - 抽象工厂模式
- 设计模式读书笔记之抽象工厂模式(Abstract Factory)
- 设计模式之二(抽象工厂模式)(Abstract Factory)
- Java设计模式之抽象工厂(Abstract Factory)模式
- 设计模式之(十一、抽象工厂模式Abstract Factory)
- JAVA设计模式之抽象工厂(Abstract Factory)模式
- 设计模式-创建型模式之 Abstract Factory(抽象工厂)
- 设计模式之六 --- 抽象工厂模式(Abstract Factory)
- 设计模式之六 --- 抽象工厂模式(Abstract Factory)
- Git版本管理工具的使用
- VMware的日常问题收集
- java内存泄露和内存溢出
- GDB 多线程调试
- 最近比较受刺激。。
- 设计模式之抽象工厂模式(Abstract Factory)
- IPC ------有名管道fifo
- 包围盒算法列表
- php 文件操作
- Android Gradle Build
- Linux文件系统的的实现:创建一个文件的过程
- Codefordes round 178 div2 C
- linux64bit上安装weblogic64bit
- Yahoo!开源运行在Hadoop上的Storm——Storm-YARN