首页 > 设计模式 之美 -- 工厂方法模式

设计模式 之美 -- 工厂方法模式

文章目录

        • 1. 解决问题
        • 2. 应用场景
        • 3. 实现如下
          • C++实现
          • C语言实现
        • 4. 缺点

1. 解决问题

在简单工厂模式中,我们使用卖衣服进行举例,同一种工厂可以卖很多不同种类的衣服,工厂只是将衣服的生产过程进行了封装。

当我们增加衣服种类的时候,在简单工厂模式中需要修改工厂的代码,破坏了类的开闭原则(对扩展开发, 对修改关闭),同时增加测试成本。

此时为了避免这种问题的出现,我们推出工厂方法模式,为每个商品封装指定的工厂方法,这样商品种类增加时对于工厂只需要增加指定的工厂就可以了。

2. 应用场景

  • 逻辑中会经常使用到该类对象(需要经常进行new、malloc操作)
  • 逻辑后续会有一定规模,最好这个时候就将对象的创建和使用分离
  • 后续会小范围扩展产品类型
  • 程序规模比较大,不希望每次增加产品后都对之前逻辑重新测试

3. 实现如下

C++实现

实现功能:还是卖衣服,针对每一种衣服创建指定的工厂,由工厂封装对象的创建过程。

#include using namespace std;/*工厂的可以制造的衣服种类*/
enum ClothType{ hat,paths};class Cloth{ public:virtual void createCloth(void) = 0;virtual ~Cloth(){ } //定义为虚函数,对象空间回收时则会调用子类的析构函数
};/*帽子类*/
class Hat: public Cloth{ public:Hat(){ cout << "Hat::hat()" << endl;}virtual void createCloth(void) { cout << "Hat::createHat()" << endl;}~Hat(){ cout << "Hat::delete()" << endl;}
};/*裤子类*/
class Paths: public Cloth{ public:Paths(){ cout << "Paths::paths()" << endl;}virtual void createCloth(void) { cout << "Paths::createPaths()" << endl;}~Paths(){ cout << "Paths::delete()" << endl;}
};/*工厂方法类,用来创建工厂*/
class Factory{ 
public:virtual Cloth *CreateProduct() = 0;    
};/*帽子工厂,创建帽子*/
class FactoryHat : public Factory
{ 
public:Cloth *CreateProduct(){ return new Hat ();}
};/*裤子工厂,创建裤子*/
class FactoryPaths : public Factory
{ 
public:Cloth *CreateProduct(){ return new Paths ();}
};int main()
{ Factory *factoryHat = new FactoryHat();Cloth *hat = factoryHat -> CreateProduct();hat -> createCloth();Factory *factoryPaths = new FactoryPaths();Cloth *paths = factoryPaths -> CreateProduct();paths -> createCloth();if(NULL != factoryHat) { delete factoryHat;factoryHat = NULL;}if(NULL != factoryPaths) { delete factoryPaths;factoryPaths = NULL;}if(NULL != hat) { delete hat;hat = NULL;}if(NULL != paths) { delete paths;paths = NULL;}return 0;
}
C语言实现

实现功能:生产橘子和苹果两种水果

/*用C语言实现工厂方法模式*/
#include 
#include 
#include 
#include enum { GRAPE,APPLE};typedef struct _Apple
{ void (*print_apple)();
}Apple;typedef struct _Grape
{ void (*print_grape)();
}Grape;void print_apple()
{ printf("apple!
");
}void print_grape()
{ printf("grape!
");
}Apple* sell_apple()
{ Apple* pApple = (Apple*)malloc(sizeof(Apple));assert(NULL != pApple);pApple->print_apple = print_apple;return pApple;
}Grape* sell_grape()
{ Grape* pGrape = (Grape*)malloc(sizeof(Grape));assert(NULL != pGrape);pGrape->print_grape = print_grape;return pGrape;
}typedef struct _FruitShop
{ void* (*sell_fruit)();
}FruitShop;FruitShop* create_fruit_shop(int fruit)
{ FruitShop* pFruitShop = (FruitShop*)malloc(sizeof(FruitShop));assert(NULL != pFruitShop);if (GRAPE == fruit){ pFruitShop->sell_fruit = (void *(*)())sell_apple;}else if(APPLE == fruit){ pFruitShop->sell_fruit = (void *(*)())sell_grape;}else{ return NULL;}return pFruitShop;
}int main()
{ FruitShop* apple = NULL;Apple* a = NULL;apple = create_fruit_shop(APPLE);a = (Apple *)apple->sell_fruit();a->print_apple();FruitShop* grape = NULL;Grape* g = NULL;grape = create_fruit_shop(GRAPE);g = (Grape*)grape->sell_fruit();g->print_grape();if(g != NULL){ delete g;}if(grape != NULL){ delete grape;}if(a != NULL){ delete a;}if(apple != NULL){ delete apple;}return 0;
}

4. 缺点

1、后续产品种类特别多的时候,需要建立很多工厂,导致程序熵值太大

2、对于有多个依赖关系的种类,如果仍然建立多个工厂,则会增加很多重复逻辑

更多相关:

  • 在使用空时,习惯这么赋值  int *p = NULL;  编译器进行解释程序时,NULL会被直接解释成0,所以这里的参数根本就不是大家所想的NULL,参数已经被编译器偷偷换成了0,0是整数。  因此这面的问题就尴尬了 不好意思图片引用于网络中。 为啥呢不是this is the ptr function…这个。这就是C++中的...

  • var d= {a: 1,b: null,c: 3,d: undefined };Object.keys(d).forEach(k=>d[k]==null&&delete d[k]);//去掉值为null或undefined的对象属性//Object.keys(d).forEach(k=>(d[k]==null||d[k]==='')...

  • //ES6获取浏览器url跟参 public getUrlParam = a => (a = location.search.substr(1).match(new RegExp(`(^|&)${a}=([^&]*)(&|$)`)),a?a[2]:null);...

  • 在服务端数据库的处理当中,涉及中文字符的结构体字段,需要转为Utf8后再存储到表项中。从数据库中取出包含中文字符的字段后,如果需要保存到char *类型的结构体成员中,需要转为Ansi后再保存。从数据库中取出类型数字的字段后,如果需要保存到int型的结构体成员中,需要调用atoi函数进行处理后再保存。 1 static char *...

  • 简单工厂,工厂方法,抽象工厂都属于设计模式中的创建型模式。其主要功能都是帮助我们把对象的实例化部分抽取了出来,优化了系统的架构,并且增强了系统的扩展性。 本文是本人对这三种模式学习后的一个小结以及对他们之间的区别的理解。   简单工厂 简单工厂模式的工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的对象实例。...

  • 简介 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。 不同点 为了更清晰地理解抽象工厂模式,需要先引入两个概念:产品等级结构 :产品等级结构即产品的继承结构,如一个抽象类是CPU,其子类有intel...

  • 工厂方法模式: 一个抽象产品类,可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类只能创建一个具体产品类的实例。 抽象工厂模式: 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类可以创建多个具体产品类的实例。 区别:...

  • 又重头想了一下还是以配电脑为例最开始的时候,需要电脑,你得自己去生产电脑的每一个组件,例如你要cpu 就得自己生产cpu 要主板就得自己生产主板。于是出现 简单工厂模式在简单工厂模式中,定义一个返回接口,然后所有的组件实例都从这个工厂中产生例: 工厂---------生产硬件 硬件----------...

  • 因为函数参数是按值传递的,所以要想改变变量,必须传递地址。 二级指针实际上就是指针变量的地址,如果传递二级指针,函数声明必须写**。 (void**)&必须是本质上就是指针变量的地址才可以做这样的转换,并不是说把一个一级指针也可以转换,void**的本质是标识一个二级指针。 &data就是(默认数据类型 **)&data,(void...

  • 文章目录1. 解决问题2. 应用场景3. 实现如下:C++实现C语言实现4. 缺点 1. 解决问题 在工厂方法模式中,我们卖衣服。此时我们为每一种衣服创建不同的工厂,帽子有一个工厂专门创建,裤子有一个工厂专门创建,T恤有一个工厂专门创建。这样的方式保证了代码设计的开闭原则(对扩展开发,对修改关闭),解决了简单工厂模式中暴露的...

  • 转载于:http://blog.csdn.net/u012819339/article/details/50654764   实体作品请参看优酷视频。 若以上链接点击无效请把该链接地址复制到浏览器地址栏 http://v.youku.com/v_show/id_XODYzODczNzQ4.html 说明: 该作品为arvik于2014...

  • - (void)viewDidLoad {[super viewDidLoad];NSLog(@"我在玩手机");NSLog(@"手机没电了");[self chargeMyIphone:^{NSLog(@"出门逛街");}];NSLog(@"我在看电视"); }-(void)chargeMyIphone:(void(^)(void...

  • http://stackoverflow.com/questions/150446/how-do-i-detect-when-someone-shakes-an-iphone 我的实现(基于Eran Talmor): 没必要application.applicationSupportsShakeToEdit = YES; Set th...