意图
定义一个用于创建对象的接口,让子类决定实例化哪一个类。该模式使一个类的实例化延迟到其子类。
动机
框架使用抽象类定义和维护对象之间的关系。这些对象的创建通常也由框架负责。
适用性
- 当一个类不知道它所必须创建的对象的类的时候。
- 当一个类希望由它的子类来指定它创建的对象的时候。
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
类图
例子场景
假设你有一家披萨店,你的加盟店希望所有订单处理都一致,每个披萨店的主要差异在于比萨风味,比如纽约披萨的薄饼,芝加哥比萨的厚饼,每个披萨需要做一些准备(和面、加上佐料),然后烘烤、切片、装盒。
实现
Pizza.h
#pragma once
#include <string>
#include <vector>
class Pizza
{
public:
Pizza();
virtual void prepare();
virtual void bake();
virtual void cut();
virtual void box();
protected:
std::string m_name;
std::string m_dough;
std::string m_sauce;
std::vector<std::string> m_toppings;
};
Pizza.cpp
#include "Pizza.h"
#include <iostream>
Pizza::Pizza()
{
}
void Pizza::prepare()
{
std::cout << "Preparing " << m_name << std::endl;
std::cout << "Tossing dough..." << std::endl;
std::cout << "Adding sauce..." << std::endl;
std::cout << "Add toppings: ";
for (size_t i = 0;i < m_toppings.size(); ++i)
{
std::cout << m_toppings[i];
}
std::cout << std::endl;
}
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;
}
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();
}
NYPizzaStore.h
#pragma once
#include "PizzaStore.h"
class Pizza;
class NYPizzaStore : public PizzaStore
{
public:
NYPizzaStore();
Pizza *createPizza(const std::string& pizzaName) override;
};
NYPizzaStore.cpp
#include "NYPizzaStore.h"
#include "NYStyleCheesePizza.h"
NYPizzaStore::NYPizzaStore()
{
}
Pizza* NYPizzaStore::createPizza(const std::string& pizzaName)
{
Pizza* pPizza = nullptr;
if (pizzaName == "Cheese")
{
pPizza = new NYStyleCheesePizza();
}
return pPizza;
}
NYStyleCheesePizza.h
#pragma once
#include "Pizza.h"
class NYStyleCheesePizza : public Pizza
{
public:
NYStyleCheesePizza();
};
NYStyleCheesePizza.cpp
#include "NYStyleCheesePizza.h"
NYStyleCheesePizza::NYStyleCheesePizza()
{
m_name = "NY Style Sauce and Cheese Pizza";
m_dough = "Thin Crust Dough";
m_sauce = "Marinara Sauce";
m_toppings.push_back("Grated Reggiano CHeese");
}
ChicagoPizzaStore.h
#pragma once
#include "PizzaStore.h"
class ChicagoPizzaStore : public PizzaStore
{
public:
ChicagoPizzaStore();
Pizza* createPizza(const std::string& pizzaName) override;
};
ChicagoPizzaStore.cpp
#include "ChicagoPizzaStore.h"
#include "ChicagoStyleCheesePizza.h"
ChicagoPizzaStore::ChicagoPizzaStore()
{
}
Pizza* ChicagoPizzaStore::createPizza(const std::string& pizzaName)
{
Pizza* pPizza = nullptr;
if (pizzaName == "Cheese")
{
pPizza = new ChicagoStyleCheesePizza();
}
return pPizza;
}
ChicagoStyleCheesePizza.h
#pragma once
#include "Pizza.h"
class ChicagoStyleCheesePizza : public Pizza
{
public:
ChicagoStyleCheesePizza();
void cut() override;
};
ChicagoStyleCheesePizza.cpp
#include "ChicagoStyleCheesePizza.h"
#include <iostream>
ChicagoStyleCheesePizza::ChicagoStyleCheesePizza()
{
m_name = "Chicago Style Deep Dish Cheese Pizza";
m_dough = "Extra Thick Crust Dough";
m_sauce = "Plum Tomato Sauce";
m_toppings.push_back("Shredded Mozzarella Cheese");
}
void ChicagoStyleCheesePizza::cut()
{
std::cout << "Cutting the pizza into square slices"<<std::endl;
}
main.cpp
#include "ChicagoPizzaStore.h"
#include "NYPizzaStore.h"
#include <memory>
#include <iostream>
int main()
{
std::shared_ptr<PizzaStore> pChicagoPizzaStore = std::make_shared<ChicagoPizzaStore>();
std::shared_ptr<PizzaStore> pNYPizzaStore = std::make_shared<NYPizzaStore>();
pChicagoPizzaStore->orderPizza("Cheese");
std::cout << std::endl;
pNYPizzaStore->orderPizza("Cheese");
return 0;
}