Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1793617
  • 博文数量: 438
  • 博客积分: 9799
  • 博客等级: 中将
  • 技术积分: 6092
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-25 17:25
文章分类

全部博文(438)

文章存档

2019年(1)

2013年(8)

2012年(429)

分类: C/C++

2012-03-25 18:51:20

注意区分“简单工厂”、“工厂方法模式”和“抽象工厂模式”

如果你需要动态选择实例化的类型,可以通过条件判断来选择类型。比如餐馆点菜:


  1. class Restaurant
  2. {
  3. public:
  4.     Food* order(string s)
  5.     {
  6.         if (s == "rice")
  7.             return new Rice;
  8.         if (s == "meat")
  9.             return new Meat;
  10.         if (s == "vegetable")
  11.             return new Vegetable;
  12.         return NULL;
  13.     }

  14. };

这样做的坏处是什么?当然是不容易适应变化。如果你要加一个饮料,那就要加一个条件分支。如果白菜断货了,餐馆就要删除一个条件分支。餐馆不应该根据菜式频繁地变化,所以可以把这些变化提取出来,形成一个简单工厂:


  1. class FoodFactory
  2. {
  3. public:
  4.     Food* createFood(string s)
  5.     {
  6.         if (s == "rice")
  7.             return new Rice;
  8.         if (s == "meat")
  9.             return new Meat;
  10.         if (s == "vegetable")
  11.             return new Vegetable;
  12.         return NULL;
  13.     }
  14. };

这时餐馆的代码可以简化成:


  1. class Restaurant
  2. {
  3. public:
  4.     Food* order(string s)
  5.     {
  6.         FoodFactory* pFactory = new FoodFactory;
  7.         return pFactory->createFood(s);
  8.     }
  9. };

这样,所有的变化都局限于那个简单工厂了。你或许有疑问,这样做不就是仅仅把变化从餐馆移到了工厂吗?有什么本质区别?区别在于:这个工厂变得可以被复用了。餐馆,快餐,中餐,西餐都可以从这个工厂进货。

简单工厂并不是一个模式,只不过是常用的一种的习惯。

为了让工厂具有可扩展性,我们可以把工厂抽象成一个抽象类。


  1. class FoodFactory
  2. {
  3. public:
  4.     virtual Food* creatFood(string s) = 0;
  5. };

各种生产食物的工厂都可以继承这个抽象类,并实现自己的的createFood方法,这样餐馆可以选择不同的菜系,比如它可以扩展成做西餐:


  1. class Restaurant
  2. {
  3. public:
  4.     Food* order(string s)
  5.     {
  6.         FoodFactory* pFactory = new WesternFoodFactory;
  7.         return pFactory->createFood(s);
  8.     }
  9. };

这种基于同一个抽象工厂类形成的类层次结构被称为工厂方法模式。同样要注意到这个模式依赖于另一个抽象类层次:产品(即上例中的Food)。

设计原则:要依赖抽象,不要依赖具体类。(依赖倒置原则)

另一种工厂模式是抽象工厂模式。它是一个接口,定义了生产各种原料的方法。比如一个创建Car的工厂可以是这样:


  1. interface ICarFactory
  2. {
  3.     virtual Wheel* createWheel() = 0;
  4.     virtual Shell* createShell() = 0;
  5.     virtual Engine* createEngine() = 0;
  6. };

这样的话就可以跟据不同需要组装成一部车出来:


  1. class RaceCar
  2. {
  3. public:
  4.     RaceCar()
  5.     {
  6.         ICarFactory* pFactory = new IRaceCarFactory();
  7.         this->engine = pFactory->createEngine();
  8.         this->shell = pFactory->createShell();
  9.         this->wheel = pFacotry->createWheel();
  10.     }
  11. };

阅读(777) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~