意图
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。
动机
考虑一个支持多种视感标准的用户界面工具包,例如Motif和Presentation Manager。不同的视感风格为诸如滚动条、窗口和按钮等用户界面“窗口组件”定义不同的外观和行为。为保证视感风格标准间的可移植性,一个应用不应该为特定的视感外观硬编码它的窗口组件。在整个应用中实例化特定视感风格的窗口组件类将使得以后很难改变视感风格。
适用性
- 一个系统要独立于它的产品的创建、组合和表示时。
- 一个系统要由多个产品系列中的一个来配置时。
- 当你要强调一系列相关的产品对的设计以便进行联合使用时。
- 当你提供一个产品类库,而只想显示它们的接口而不是实现时。
类图
例子场景
假设你有一家披萨店,每个披萨需要做一些准备(和面、加上佐料),然后烘烤、切片、装盒,每个调料都是这家店特有的工厂提供。
实现
PizzaStore.h
#pragma once
#include <string>
class Pizza;
class PizzaStore
{
public:
PizzaStore();
void orderPizza(const std::string& pizzaName);
virtual Pizza* createPizza(const std::string& pizzaName)=0;
};
PizzaStore.cpp
#include "PizzaStore.h"
#include "Pizza.h"
#include <memory>
PizzaStore::PizzaStore()
{
}
void PizzaStore::orderPizza(const std::string& pizzaName)
{
std::shared_ptr<Pizza> pPizza;
pPizza.reset(createPizza(pizzaName));
pPizza->prepare();
pPizza->bake();
pPizza->cut();
pPizza->box();
}
PizzaStore.h
#pragma once
#include "PizzaStore.h"
class Pizza;
class NYPizzaStore : public PizzaStore
{
public:
NYPizzaStore();
Pizza *createPizza(const std::string& pizzaName) override;
};
PizzaStore.cpp
#include "NYPizzaStore.h"
#include "NYStyleCheesePizza.h"
#include "NYPizzaIngredientFactory.h"
NYPizzaStore::NYPizzaStore()
{
}
Pizza* NYPizzaStore::createPizza(const std::string& pizzaName)
{
Pizza* pPizza = nullptr;
if (pizzaName == "Cheese")
{
pPizza = new NYStyleCheesePizza(new NYPizzaIngredientFactory());
}
return pPizza;
}
Pizza.h
#pragma once
#include <string>
#include <vector>
class Dough;
class Sauce;
class Cheese;
class PizzaIngredientFactory;
class Pizza
{
public:
Pizza();
virtual void prepare()=0;
virtual void bake();
virtual void cut();
virtual void box();
protected:
std::string m_name;
Dough* m_pDough;
Sauce* m_pSauce;
Cheese* m_pCheese;
PizzaIngredientFactory* m_pPizzaIngredientFactory;
};
Pizza.cpp
#include "Pizza.h"
#include <iostream>
Pizza::Pizza()
{
}
void Pizza::bake()
{
std::cout << "Bake for 25 minutes at 350"<<std::endl;
}
void Pizza::cut()
{
std::cout << "Cutting the pizza into diagonal slices" << std::endl;
}
void Pizza::box()
{
std::cout << "Place pizza in official PizzaStore box" << std::endl;
}
NYStyleCheesePizza.h
#pragma once
#include "Pizza.h"
class PizzaIngredientFactory;
class NYStyleCheesePizza : public Pizza
{
public:
NYStyleCheesePizza(PizzaIngredientFactory* pPizzaIngredientFactory);
void prepare() override;
};
NYStyleCheesePizza.cpp
#include "NYStyleCheesePizza.h"
#include "PizzaIngredientFactory.h"
#include "Dough.h"
#include "Cheese.h"
#include "Sauce.h"
#include <iostream>
NYStyleCheesePizza::NYStyleCheesePizza(PizzaIngredientFactory* pPizzaIngredientFactory)
{
m_name = "NY Style Sauce and Cheese Pizza";
m_pPizzaIngredientFactory = pPizzaIngredientFactory;
}
void NYStyleCheesePizza::prepare()
{
std::cout << "Prepareing " << m_name << std::endl;
m_pDough = m_pPizzaIngredientFactory->createDough();
m_pCheese = m_pPizzaIngredientFactory->createCheese();
m_pSauce = m_pPizzaIngredientFactory->createSauce();
std::cout << "Dough:" << m_pDough->getDescription() << std::endl;
std::cout << "Sauce:" << m_pSauce->getDescription() << std::endl;
std::cout << "Cheese:" << m_pCheese->getDescription() << std::endl;
}
Cheese.h
#pragma once
#include <iostream>
class Cheese
{
public:
Cheese();
virtual std::string getDescription() = 0;
};
Cheese.cpp
#include "Cheese.h"
Cheese::Cheese()
{
}
ReggianoCheese.h
#pragma once
#include "Cheese.h"
class ReggianoCheese : public Cheese
{
public:
ReggianoCheese();
std::string getDescription() override;
};
ReggianoCheese.cpp
#include "ReggianoCheese.h"
#include <iostream>
ReggianoCheese::ReggianoCheese()
{
}
std::string ReggianoCheese::getDescription()
{
return "Reggiano Cheese";
}
Dough.h
#pragma once
#include <iostream>
class Dough
{
public:
Dough();
virtual std::string getDescription() = 0;
};
Dough.cpp
#include "Dough.h"
Dough::Dough()
{
}
ThinCrustDough.h
#pragma once
#include "Dough.h"
#include <string>
class ThinCrustDough : public Dough
{
public:
ThinCrustDough();
std::string getDescription() override;
};
ThinCrustDough.cpp
#include "ThinCrustDough.h"
#include <iostream>
ThinCrustDough::ThinCrustDough()
{
}
std::string ThinCrustDough::getDescription()
{
return "Thin Crust Dough";
}
Sauce.h
#pragma once
#include <iostream>
class Sauce
{
public:
Sauce();
virtual std::string getDescription() = 0;
};
Sauce.cpp
#include "Sauce.h"
Sauce::Sauce()
{
}
MarinaraSauce.h
#pragma once
#include "Sauce.h"
class MarinaraSauce : public Sauce
{
public:
MarinaraSauce();
std::string getDescription() override;
};
MarinaraSauce.cpp
#include "MarinaraSauce.h"
#include <iostream>
MarinaraSauce::MarinaraSauce()
{
}
std::string MarinaraSauce::getDescription()
{
return "Marinara Sauce";
}
main.cpp
#include "NYPizzaStore.h"
#include <memory>
#include <iostream>
int main()
{
std::shared_ptr<PizzaStore> pNYPizzaStore = std::make_shared<NYPizzaStore>();
pNYPizzaStore->orderPizza("Cheese");
return 0;
}