设计模式之实现----几种工厂模式

1.工厂方法模式:

/*************************************

   CPizza.h

*************************************/

#pragma once
#include <iostream>
using namespace std;

class CPizza
{
public:
 virtual string getDescription() = 0;
};

class CNYCheesePizza : public CPizza
{
public:
 string getDescription(){
  return string("a new york cheese pizza");
 }
};

class CNYTomatoPizza : public CPizza
{
public:
 string getDescription(){
  return string("a new york tomato pizza");
 }
};

class CNYMixPizza : public CPizza
{
public:
 string getDescription(){
  return string("a new york mix pizza");
 }
};

class CChicagoCheesePizza : public CPizza
{
public:
 string getDescription(){
  return string("a Chicago cheese pizza");
 }
};

class CChicagoTomatoPizza : public CPizza
{
public:
 string getDescription(){
  return string("a Chicago tomato pizza");
 }
};

class CChicagoMixPizza : public CPizza
{
public:
 string getDescription(){
  return string("a Chicago mix pizza");
 }
};

/**********************************************

CPizzaStore.h

*********************************************/

#include <iostream>
#include "CPizza.h"
using namespace std;


/*
工厂方法是一种is-a的关系,这个是比萨店的虚基类。
所有实比萨店必须要从这里派生出去,并重载

也就是工厂方法与简单工厂的区别,工厂方法把工厂的实现延迟到子类去决定
*/

class CPizzaStore
{
public:
 CPizza* orderPizza(const string& _pizzaName){

  //简单工厂方法,来做一个比萨
  CPizza* pizza = createPizza(_pizzaName);

  //对比萨做一些其它处理
  bake(pizza);
  cut(pizza);
  box(pizza);

  return pizza;
 }

 void bake(CPizza* pz){};

 void cut(CPizza* pz){};

 void box(CPizza* pz){};

 ////////////////////////////////////////////////////////////////////////
 //这个函数是工厂方法的根本。。。。。。。。。。。。。。。。。。。
 //子类必须将其重载
 virtual CPizza* createPizza(const string& _pizzaName) = 0;
};

//开一家纽约风味的比萨店,注意在这里要实现createPizza()工厂方法
class CNYPizzaStore : public CPizzaStore
{
public:
 CPizza* createPizza(const string& _pizzaName){
  //查找pizza种类,做类型匹配
  map<string, pizzaType>::iterator ifind = g_pizzatype.find(_pizzaName);
  if(ifind == g_pizzatype.end())
   return NULL;

  CPizza* pizza = NULL;

  switch(ifind->second)
  {
  case PT_CHEESE:
   pizza = new CNYCheesePizza();
   break;
  case PT_TOMATO:
   pizza = new CNYTomatoPizza();
   break;
  case PT_MIX:
   pizza = new CNYMixPizza();
   break;
  }

  return pizza;
 }
};

//开一家纽约风味的比萨店,注意在这里要实现真正的pizza类
class CChicagoPizzaStore : public CPizzaStore
{
public:
 CPizza* createPizza(const string& _pizzaName){
  //查找pizza种类,做类型匹配
  map<string, pizzaType>::iterator ifind = g_pizzatype.find(_pizzaName);
  if(ifind == g_pizzatype.end())
   return NULL;

  CPizza* pizza = NULL;

  switch(ifind->second)
  {
  case PT_CHEESE:
   pizza = new CChicagoCheesePizza();
   break;
  case PT_TOMATO:
   pizza = new CChicagoTomatoPizza();
   break;
  case PT_MIX:
   pizza = new CChicagoMixPizza();
   break;
  }

  return pizza;
 }
};

/*********************************************************

PizzaType.h

*********************************************************/

#pragma once;
#include <map>
#include <string>
using namespace std;

enum pizzaType{
 PT_CHEESE = 1,
 PT_TOMATO,
 PT_MIX,
};

map<string, pizzaType> g_pizzatype;

void buildMapping(map<string, pizzaType>& g_pizzatype)
{
 g_pizzatype.insert(make_pair("cheese", PT_CHEESE));
 g_pizzatype.insert(make_pair("tomato", PT_TOMATO));
 g_pizzatype.insert(make_pair("mix", PT_MIX));
}

/**********************************************************

main.h

***********************************************************/

/*
设计模式:  工厂方法模式: is a关系

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪些一个。工厂方法让类把实例化推迟到子类。
所有的工厂模式都用来封闭对象的创建。工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封闭的目的。


简单工厂与工厂方法之间的区别:
1. 简单工厂是一种has-a的关系,所有的产口是由店铺中的一个工厂成员所创建的。而工厂方法是一种is-a的关系,它把创建产品的事情留给了工厂方法的子类去决定如何创建。
2. 简单工厂把全部的事情,在一个地方都处理完了,然而工厂方法却是创建一个框架,让子类决定要如何实现。
3. 简单工厂的做法,可以将对象的创建封装起来,但是简单工厂不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。

 

抽象工厂与工厂方法的区别:
1. 工厂方法用的是继承, 抽象工厂用的是组合。
这就意味着用工厂方法创建对象需要扩展一个类,并覆盖它的工作方法。工厂方法通过子类来创建对象。用这种做法,客户只需只知道他们所使用的抽象类型就可以了,而由子类来负责决定具体类型。换句话说,工厂方法只负责将客户从具体类型中解耦。
抽象工厂提供一个用来创建一个“产品家族”的抽象类型,这个类型的子类定义了产品被产生的方法。要想使用这个工厂,必须先实例化它,然后将它传入一些针对抽象类型所写的代码事。所以,和工厂方法一样,抽象工厂也可以将客户从具体类型中解耦。要创建产品家族中的某个产品,我们可以通过调用抽象工厂的对应生产此产品的方法。这些方法必须要抽象工厂的实体子类中重载实现。
2. 扩展性和修改性
对于抽象工厂,如果想在“产品家族”中加入新(修改)产品就必须新增(改变)其抽象的接口,改变接口就是意味着必须深入改变每个子类的接口!
而工厂方法不存在这个问题,因为工厂方法只是用来创建一个产品。:(


by 何戬, hejian@cad.zju.edu.cn
*/


#include <iostream>
#include "pizzaType.h"
#include "CPizzaStore.h"
using namespace std;

int main()

 buildMapping(g_pizzatype);

 /*//类型匹配
 map<string, pizzaType>::iterator ifind = g_pizzatype.find("cheese");
 if(ifind == g_pizzatype.end())
 return 0;
 cout<<ifind->first<<ifind->second<<endl;
 */

 CPizzaStore* nypizzaStore = new CNYPizzaStore();
 CPizza* p1 = nypizzaStore->orderPizza("cheese");
 CPizza* p2 = nypizzaStore->orderPizza("mix");
 cout<<p1->getDescription()<<endl;
 cout<<p2->getDescription()<<endl;

 CPizzaStore* chipizzaStore = new CChicagoPizzaStore();
 CPizza* p3 = chipizzaStore->orderPizza("cheese");
 CPizza* p4 = chipizzaStore->orderPizza("mix");
 cout<<p3->getDescription()<<endl;
 cout<<p4->getDescription()<<endl;


 delete p4;
 delete p3;
 delete p2;
 delete p1;
 delete nypizzaStore;

 return 0;
}

 

2.简单工厂:

/***************************************************************

CPizza.h

***************************************************************/

#pragma once
#include <iostream>
using namespace std;

class CPizza
{
public:
 virtual string getDescription() = 0;
};

class CCheesePizza : public CPizza
{
public:
 string getDescription(){
  return string("a cheese pizza");
 }
};

class CTomatoPizza : public CPizza
{
public:
 string getDescription(){
  return string("a tomato pizza");
 }
};

class CMixPizza : public CPizza
{
public:
 string getDescription(){
  return string("a mix pizza");
 }
};

/********************************************************

CPizzaStore.h

********************************************************/

#include <iostream>
#include "simpleFactory.h"
using namespace std;


/*
简单工厂是一种has-a的关系,所有的产口是由店铺中的一个工厂成员所创建的。
*/
class CPizzaStore
{
private:
 //用于产生比萨的工厂
 CSimpleFactory* m_PizzaFactory;

public:
 //用策略模式来更改工厂
 void setNewFactory(CSimpleFactory* _PizzaFactory){
  if(!_PizzaFactory)
   return;
  m_PizzaFactory = _PizzaFactory;
 }

 CPizzaStore(CSimpleFactory* _PizzaFactory){
  m_PizzaFactory = _PizzaFactory;
 }

 CPizza* orderPizza(const string& _pizzaName){
  if(!m_PizzaFactory)
   return NULL;

  //简单工厂方法,来做一个比萨
  CPizza* pizza = m_PizzaFactory->makePizza(_pizzaName);

  //对比萨做一些其它处理
  bake(pizza);
  cut(pizza);
  box(pizza);

  return pizza;
 }

 void bake(CPizza* pz){};

 void cut(CPizza* pz){};

 void box(CPizza* pz){};
};

/******************************************************

pizzaType.h

******************************************************/

#pragma once;
#include <map>
#include <string>
using namespace std;

enum pizzaType{
 PT_CHEESE = 1,
 PT_TOMATO,
 PT_MIX,
};

map<string, pizzaType> g_pizzatype;

void buildMapping(map<string, pizzaType>& g_pizzatype)
{
 g_pizzatype.insert(make_pair("cheese", PT_CHEESE));
 g_pizzatype.insert(make_pair("tomato", PT_TOMATO));
 g_pizzatype.insert(make_pair("mix", PT_MIX));
}

/********************************************************

simpleFactory.h

********************************************************/

/*
 一个简单工厂的类
*/

#include <iostream>
#include "pizzaType.h"
#include "CPizza.h"
using namespace std;

 

class CSimpleFactory
{
public:

 CPizza* makePizza(const string& pizzaname){

  //查找pizza种类,做类型匹配
  map<string, pizzaType>::iterator ifind = g_pizzatype.find(pizzaname);
  if(ifind == g_pizzatype.end())
   return NULL;

  CPizza* pizza = NULL;
  
  switch(ifind->second)
  {
  case PT_CHEESE:
   pizza = new CCheesePizza();
   break;
  case PT_TOMATO:
   pizza = new CTomatoPizza();
   break;
  case PT_MIX:
   pizza = new CMixPizza();
   break;
  }

  return pizza;
 }
};

/*************************************************

testSimpleFactory.cpp

*************************************************/

/*
    设计模式:  简单工厂, has a 关系

 简单工厂其实不是一个设计模式,反而比较是一种编程习惯。但经常被使用。
 虽然我们可以定义一个静态的工厂方法(称为静态工厂),这样可以避免实例化一个工厂类。但是,这样做的话就不能通过继承来改变创建方法的行为。


 简单工厂与工厂方法之间的区别:
 1. 简单工厂是一种has-a的关系,所有的产口是由店铺中的一个工厂成员所创建的。而工厂方法是一种is-a的关系,它把创建产品的事情留给了工厂方法的子类去决定如何创建。
 2. 简单工厂把全部的事情,在一个地方都处理完了,然而工厂方法却是创建一个框架,让子类决定要如何实现。
 3. 简单工厂的做法,可以将对象的创建封装起来,但是简单工厂不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。

 

 by 何戬, hejian@cad.zju.edu.cn
*/
#include <iostream>
#include "pizzaType.h"
#include "CPizzaStore.h"
using namespace std;


int main()
{
 buildMapping(g_pizzatype);
 
 /*//类型匹配
 map<string, pizzaType>::iterator ifind = g_pizzatype.find("cheese");
 if(ifind == g_pizzatype.end())
  return 0;
 cout<<ifind->first<<ifind->second<<endl;
 */

 CSimpleFactory* sf = new CSimpleFactory();

 CPizzaStore* pizzaStore = new CPizzaStore(sf);

 CPizza* aCheesPizza = pizzaStore->orderPizza("tomato");
 cout<<aCheesPizza->getDescription()<<endl;;

 delete aCheesPizza;
 delete pizzaStore;
 delete sf;

 return 0;
}

3.抽象工厂模式

/*
    抽象工厂的方法经常以工厂方法的方式实现。
 抽象工厂的任务是定义一个负责创建"一组"产品的接口。
 这个接口内的每个方法都负责创建一个具体产品。
 同时我们利用实现抽象工厂的子类来提供这些具体的做法。所以在抽象工厂中利用工厂方法是相当自然的做法。

 by 何戬, hejian@cad.zju.edu.cn
*/

/*******************************************************

AbstractFactory.h

*******************************************************/


#pragma once
#include <iostream>
#include "pizzaType.h"
#include "CPizza.h"
#include "CIngredient.h"
using namespace std;


//////////////////////////////////////////////////
//抽象工厂模式的虚基类
//虚基类定义了创建对象家族的接口
//一般地,每一个对象用一个接口来创建
//暂定这个抽象工厂是用来
class CAbstractIngredientFactory
{
 /*
 tomato和sugar是可以看成是同一家庭的产品
 */
public:
 //定义创建tomato对象的基类成员
 virtual CTomato* getTomato() = 0;
 //定义创建Sugar对象的基类成员
 virtual CSugar*  getSugar() = 0;
};


///////////////////////////////////////////////
//定义一个纽约的原料工厂
class CNYIngredientFactory : public CAbstractIngredientFactory
{
public:
 virtual CTomato* getTomato(){
  return new CSweetTomato();
 }

 virtual CSugar* getSugar(){
  return new CWhiteSugar();
 }
};

///////////////////////////////////////////////
//定义一个纽约的原料工厂
class CChicagoIngredientFactory : public CAbstractIngredientFactory
{
public:
 virtual CTomato* getTomato(){
  return new CCommonTomato();
 }

 virtual CSugar* getSugar(){
  return new CRedSugar();
 }
};

/**********************************************************

CIngredient.h

**********************************************************/

#pragma once
#include <iostream>
using namespace std;

//比萨成份类

//tomato的基类
class CTomato
{
public:
 virtual string getDescription() = 0;
};

//非常甜的Tomato
class CSweetTomato : public CTomato
{
public:
 virtual string getDescription(){
  return "ingredient: sweet tomato";
 }
};

//普通Tomato
class CCommonTomato : public CTomato
{
public:
 virtual string getDescription(){
  return "ingredient: common tomato";
 }
};

//Sugar的基类
class CSugar
{
public:
 virtual string getDescription() = 0;
};

//白糖
class CWhiteSugar : public CSugar
{
public:
 string getDescription(){
  return "ingredient: White Sugar";
 }
};

//红糖
class CRedSugar : public CSugar
{
public:
 string getDescription(){
  return "ingredient: Red Sugar";
 }
};

 /***********************************************************

CPizza.h

***********************************************************/

#pragma once
#include <iostream>
#include "CIngredient.h"
#include "AbstractFactory.h"
using namespace std;

/////////////////////////////////////
//用抽象工厂来产生原料的比萨基类
class CPizza
{
protected:
 CTomato* m_ingedientTomato;
 CSugar*  m_ingredientSugar;

public:
 CPizza():m_ingedientTomato(NULL), m_ingredientSugar(NULL){};
 virtual string getDescription() = 0;
};

//现在制作哪个口味的比萨就是由原料工厂参数来定了。
class CCheesePizza : public CPizza
{
public:
 CCheesePizza(CAbstractIngredientFactory* _ingredientFactory){
  m_ingedientTomato   = _ingredientFactory->getTomato();
  m_ingredientSugar   = _ingredientFactory->getSugar();
 }
 string getDescription(){
  if(!m_ingedientTomato || !m_ingredientSugar)
   return "";
  string res("a new york cheese pizza");
  res += "\nTomato :";
  res += m_ingedientTomato->getDescription();
  res += "\nSugar :";
  res += m_ingredientSugar->getDescription();
  return res;
 }
};

class CTomatoPizza : public CPizza
{
public:
 CTomatoPizza(CAbstractIngredientFactory* _ingredientFactory){
  m_ingedientTomato   = _ingredientFactory->getTomato();
  m_ingredientSugar   = _ingredientFactory->getSugar();
 }

 string getDescription(){
  if(!m_ingedientTomato || !m_ingredientSugar)
   return "";
  string res("a new york tomato pizza");
  res += "\nTomato :";
  res += m_ingedientTomato->getDescription();
  res += "\nSugar :";
  res += m_ingredientSugar->getDescription();
  return res;
 }
};

class CMixPizza : public CPizza
{
public:
 CMixPizza(CAbstractIngredientFactory* _ingredientFactory){
  m_ingedientTomato   = _ingredientFactory->getTomato();
  m_ingredientSugar   = _ingredientFactory->getSugar();
 }

 string getDescription(){
  if(!m_ingedientTomato || !m_ingredientSugar)
   return "";
  string res("a new york mix pizza");
  res += "\nTomato :";
  res += m_ingedientTomato->getDescription();
  res += "\nSugar :";
  res += m_ingredientSugar->getDescription();
  return res;
 }
};

/***********************************************************

CPizzaStore.h

**********************************************************/

#pragma once
#include <iostream>
#include "CPizza.h"
#include "AbstractFactory.h"
using namespace std;


/*
抽象工厂
*/

class CPizzaStore
{
protected:
 //抽象工厂的成员变量,用来获取想要的调料
 CAbstractIngredientFactory* m_ingredientFactory;

public:
 CPizzaStore() : m_ingredientFactory(NULL){}

 CPizza* orderPizza(const string& _pizzaName){

  //简单工厂方法,来做一个比萨
  CPizza* pizza = createPizza(_pizzaName);

  //对比萨做一些其它处理
  bake(pizza);
  cut(pizza);
  box(pizza);

  return pizza;
 }

 void bake(CPizza* pz){};

 void cut(CPizza* pz){};

 void box(CPizza* pz){};

 ////////////////////////////////////////////////////////////////////////
 //这个函数是工厂方法的根本。。。。。。。。。。。。。。。。。。。
 //子类必须将其重载
 virtual CPizza* createPizza(const string& _pizzaName) = 0;
};

//开一家纽约风味的比萨店,注意在这里要实现createPizza()工厂方法
class CNYPizzaStore : public CPizzaStore
{
public:
 CNYPizzaStore(){
  m_ingredientFactory = new CNYIngredientFactory();
 }

 
 CPizza* createPizza(const string& _pizzaName){
  //查找pizza种类,做类型匹配
  map<string, pizzaType>::iterator ifind = g_pizzatype.find(_pizzaName);
  if(ifind == g_pizzatype.end())
   return NULL;

  CPizza* pizza = NULL;

  switch(ifind->second)
  {
  case PT_CHEESE:
   pizza = new CCheesePizza(m_ingredientFactory);
   break;
  case PT_TOMATO:
   pizza = new CTomatoPizza(m_ingredientFactory);
   break;
  case PT_MIX:
   pizza = new CMixPizza(m_ingredientFactory);
   break;
  }
  return pizza;
 }
};

//开一家纽约风味的比萨店,注意在这里要实现真正的pizza类
class CChicagoPizzaStore : public CPizzaStore
{
public:
 CChicagoPizzaStore(){
  m_ingredientFactory = new CChicagoIngredientFactory();
 }

 CPizza* createPizza(const string& _pizzaName){
  //查找pizza种类,做类型匹配
  map<string, pizzaType>::iterator ifind = g_pizzatype.find(_pizzaName);
  if(ifind == g_pizzatype.end())
   return NULL;

  CPizza* pizza = NULL;

  switch(ifind->second)
  {
  case PT_CHEESE:
   pizza = new CCheesePizza(m_ingredientFactory);
   break;
  case PT_TOMATO:
   pizza = new CTomatoPizza(m_ingredientFactory);
   break;
  case PT_MIX:
   pizza = new CMixPizza(m_ingredientFactory);
   break;
  }

  return pizza;
 }
};

/************************************************************

pizzaType.h

***********************************************************/

#pragma once;
#include <map>
#include <string>
using namespace std;

enum pizzaType{
 PT_CHEESE = 1,
 PT_TOMATO,
 PT_MIX,
};

map<string, pizzaType> g_pizzatype;

void buildMapping(map<string, pizzaType>& g_pizzatype)
{
 g_pizzatype.insert(make_pair("cheese", PT_CHEESE));
 g_pizzatype.insert(make_pair("tomato", PT_TOMATO));
 g_pizzatype.insert(make_pair("mix", PT_MIX));
}

/******************************************

testAbstractFactory.cpp

*******************************************/

/*
设计模式:  抽象工厂模式: has a关系

提供一个接口,用于创建相关或依赖对象的"家族",而不需要明确指定具体类。
抽象工厂的方法经常以工厂方法的方式实现。抽象工厂的任务是定义一个负责创建一组产品的接口。
这个接口内的每个方法都负责创建一个具体产品。同时我们利用实现抽象工厂的子类来提供这些具体的做法。所以在抽象工厂中利用工厂方法是相当自然的做法。


抽象工厂与工厂方法的区别:
1. 工厂方法用的是继承, 抽象工厂用的是组合。
这就意味着用工厂方法创建对象需要扩展一个类,并覆盖它的工作方法。工厂方法通过子类来创建对象。用这种做法,客户只需只知道他们所使用的抽象类型就可以了,而由子类来负责决定具体类型。换句话说,工厂方法只负责将客户从具体类型中解耦。
抽象工厂提供一个用来创建一个“产品家族”的抽象类型,这个类型的子类定义了产品被产生的方法。要想使用这个工厂,必须先实例化它,然后将它传入一些针对抽象类型所写的代码事。所以,和工厂方法一样,抽象工厂也可以将客户从具体类型中解耦。要创建产品家族中的某个产品,我们可以通过调用抽象工厂的对应生产此产品的方法。这些方法必须要抽象工厂的实体子类中重载实现。
2. 扩展性和修改性
对于抽象工厂,如果想在“产品家族”中加入新(修改)产品就必须新增(改变)其抽象的接口,改变接口就是意味着必须深入改变每个子类的接口!
而工厂方法不存在这个问题,因为工厂方法只是用来创建一个产品。:(


by 何戬, hejian@cad.zju.edu.cn

*/

#include <iostream>
#include "pizzaType.h"
#include "CPizzaStore.h"
using namespace std;

int main()

 buildMapping(g_pizzatype);

 CPizzaStore* nyps = new CNYPizzaStore();
 CPizza* p1 = nyps->orderPizza("tomato");
 cout<<p1->getDescription()<<endl;
 CPizza* p2 = nyps->orderPizza("mix");
 cout<<p2->getDescription()<<endl;


 CPizzaStore* cps = new CChicagoPizzaStore();
 CPizza* p3 = cps->orderPizza("cheese");
 cout<<p3->getDescription()<<endl;
 CPizza* p4 = cps->orderPizza("tomato");
 cout<<p4->getDescription()<<endl;

 delete p4;
 delete p3;
 delete cps;
 delete p2;
 delete p1;
 delete nyps;
}

posted on 2012-11-06 10:07  bitbit  阅读(960)  评论(0编辑  收藏  举报