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;
}