design_pattern_factory

This post implements design pattern factory in <Head First Design Pattern>. The factory design pattern has three levels, simple factory, factory method, abstract factory method. In OOP terminology, a factory is a class for creating other object. Usually, this class has methods that accept some parameters and returns some type of object depending on the parameters passed.

For the specific PizzaStore problem, we first define pizza (product).

#ifndef PIZZA_HPP_INCLUDED
#define PIZZA_HPP_INCLUDED

#include <iostream>
#include <list>

class Pizza {
protected:
    std::string name;
	std::string dough;
	std::string sauce;
	mutable std::list<std::string> toppings;

private:
    Pizza(const Pizza& );          // Disable copy constructor
	void operator=(const Pizza& ); // Disable assignment operator

public:
	Pizza() {}
	virtual ~Pizza(){};
    std::string getName() const { return name; }

	virtual void prepare() const {
		std::cout << "Preparing " << name.c_str() << std::endl;
	}

	virtual void bake() const {
		std::cout << "Baking " << name.c_str() << std::endl;
	}

	virtual void cut() const {
		std::cout << "Cutting " << name.c_str() << std::endl;
	}

	virtual void box() const {
		std::cout << "Boxing " << name.c_str() << std::endl;
	}

	void toString() const {
		/* display pizza name and ingredients */
		std::cout << "---- " << name.c_str() << " ----" << std::endl;
		std::cout << dough.c_str() << std::endl;
		std::cout << sauce.c_str() << std::endl;
		for(std::list<std::string>::iterator iterator = toppings.begin(); toppings.end() != iterator; ++iterator ) {
			std::cout << iterator->c_str() << std::endl;
		}
	}
};

class CheesePizza : public Pizza{
public:
    CheesePizza() {
		name = "Cheese Pizza";
		dough = "Regular Crust";
		sauce = "Marinara Pizza Sauce";
		toppings.push_back("Shredded Mozzarella");
		toppings.push_back("Parmesan");
	}
};

class ClamPizza : public Pizza{
public:
    ClamPizza() {
		name = "Clam Pizza";
		dough = "Thin Crust";
		sauce = "White garlic Sauce";
		toppings.push_back("Grated parmesan cheese");
		toppings.push_back("Clams");
	}
};

class PepperoniPizza : public Pizza{
public:
    PepperoniPizza(){
		name = "Pepperoni Pizza";
		dough = "Crust";
		sauce = "Marinara sauce";
		toppings.push_back("Sliced Pepperoni");
		toppings.push_back("Sliced Onion");
		toppings.push_back("Grated parmesan cheese");
	}
};

class VeggiePizza : public Pizza{
public:
    VeggiePizza(){
		name = "Veggie Pizza";
		dough = "Crust";
		sauce = "Marinara Sauce";
		toppings.push_back("Fresh Mozzarella");
		toppings.push_back("Grated Parmesan");
		toppings.push_back("Diced onion");
		toppings.push_back("Sliced mushrooms");
		toppings.push_back("Sliced red pepper");
		toppings.push_back("Sliced black olives");
	}
};

class NYStyleCheesePizza : public Pizza {
public:
    NYStyleCheesePizza() {
		name = "NY Style Sauce and Cheese Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
		toppings.push_back("Grated Reggiano Cheese");
	}
};

class NYStyleClamPizza : public Pizza {
public:
    NYStyleClamPizza() {
		name = "NY Style Clam Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
		toppings.push_back("Grated Reggiano Cheese");
		toppings.push_back("Fresh Clams from Long Island Sound");
	}
};

class NYStylePepperoniPizza : public Pizza {
public:
    NYStylePepperoniPizza() {
		name = "NY Style Pepperoni Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
		toppings.push_back("Grated Reggiano Cheese");
		toppings.push_back("Sliced Pepperoni");
		toppings.push_back("Garlic");
		toppings.push_back("Onion");
		toppings.push_back("Mushrooms");
		toppings.push_back("Red Pepper");
	}
};

class NYStyleVeggiePizza : public Pizza {
public:
    NYStyleVeggiePizza() {
		name = "NY Style Veggie Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
		toppings.push_back("Grated Reggiano Cheese");
		toppings.push_back("Garlic");
		toppings.push_back("Onion");
		toppings.push_back("Mushrooms");
		toppings.push_back("Red Pepper");
	}
};

class ChicagoStyleCheesePizza : public Pizza {
public:
    ChicagoStyleCheesePizza() {
		name = "Chicago Style Deep Dish Cheese Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
		toppings.push_back("Shredded Mozzarella Cheese");
	}

    void cut() const {
		std::cout << "Cutting the pizza into square slices" << std::endl;
	}
};

class ChicagoStyleClamPizza : public Pizza {
public:
    ChicagoStyleClamPizza() {
		name = "Chicago Style Clam Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 		toppings.push_back("Shredded Mozzarella Cheese");
		toppings.push_back("Frozen Clams from Chesapeake Bay");
	}

	void cut() const {
		std::cout << "Cutting the pizza into square slices" << std::endl;
	}
};

class ChicagoStylePepperoniPizza : public Pizza {
public:
    ChicagoStylePepperoniPizza() {
		name = "Chicago Style Pepperoni Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 		toppings.push_back("Shredded Mozzarella Cheese");
		toppings.push_back("Black Olives");
		toppings.push_back("Spinach");
		toppings.push_back("Eggplant");
		toppings.push_back("Sliced Pepperoni");
	}

	void cut() const {
		std::cout << "Cutting the pizza into square slices" << std::endl;
	}
};

class ChicagoStyleVeggiePizza : public Pizza {
public:
    ChicagoStyleVeggiePizza() {
		name = "Chicago Deep Dish Veggie Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 		toppings.push_back("Shredded Mozzarella Cheese");
		toppings.push_back("Black Olives");
		toppings.push_back("Spinach");
		toppings.push_back("Eggplant");
	}

 	void cut() const {
		std::cout << "Cutting the pizza into square slices" << std::endl;
	}
};


#endif // PIZZA_HPP_INCLUDED

Simple factor method is a simple concrete class, which has a function. The function is able to generate different objects according to the parameters.


#include <./pizza.hpp>

class SimplePizzaFactory{
public:
    Pizza* createPizza(std::string type) const {
		Pizza* pizza = 0;
		if(type.compare("cheese") == 0){
			pizza = new CheesePizza();
		}else if(type.compare("pepperoni") == 0){
			pizza = new PepperoniPizza();
		}else if(type.compare("clam") == 0){
			pizza = new ClamPizza();
		}else if(type.compare("veggie") == 0){
			pizza = new VeggiePizza();
		}
		return pizza;
    }
};

class PizzaStore{
private:
    SimplePizzaFactory* factory;

public:
    PizzaStore(SimplePizzaFactory* factory_){
		factory = factory_;
	}

	Pizza* orderPizza(std::string type){
		Pizza* pizza;
		pizza = factory->createPizza(type);
		pizza->prepare();
		pizza->bake();
		pizza->cut();
		pizza->box();

		return pizza;
	}
};
The main function is

#include <iostream>
#include <./pizza.hpp>
#include <./simplefactory.hpp>

using namespace std;

int main()
{
    SimplePizzaFactory factory;
    PizzaStore store(&factory);

    Pizza* pizza = store.orderPizza("pepperoni");
    std::cout << "We ordered a " << pizza->getName() << std::endl;

    return 0;
}


Factory method.  In factory method, such simple concrete class which has a function is replaced by an abstract class, which has a factory method, pure virtual function. The pure virtual function will be overrided by subclasses. Therefore, subclass is able to generate products according to its parameters and state. In the meantime, clients only need to deal with the abstract classCreator. One factory method is only responsible for creating one series of product (an abstract class with its various subclasses).


#include <./pizza.hpp>

class PizzaStore {
public:
    PizzaStore(){}

    virtual ~PizzaStore(){};
	virtual Pizza* createPizza(std::string type) = 0;

	Pizza* orderPizza(std::string type){
		Pizza* pizza = createPizza(type);
		std::cout << "--- Making a " << pizza->getName() << " ---" << std::endl;
		pizza->prepare();
		pizza->bake();
		pizza->cut();
		pizza->box();
		return pizza;
	}
};

class NYPizzaStore : public PizzaStore {
public:
    virtual Pizza* createPizza(std::string type){
        Pizza* pizza=NULL;

		if(type.compare("cheese") == 0){
			return pizza = new NYStyleCheesePizza();
		} else if(type.compare("veggie") == 0){
			return pizza = new NYStyleVeggiePizza();
		} else if(type.compare("clam") == 0){
			return pizza = new NYStyleClamPizza();
		} else if(type.compare("pepperoni") == 0){
			return pizza = new NYStylePepperoniPizza();
		} else {
            return pizza = NULL;
		}
	}
};

class ChicagoPizzaStore : public PizzaStore{
public:
    virtual Pizza* createPizza(std::string type){
        Pizza* pizza=NULL;

		if(type.compare("cheese") == 0){
			return pizza = new ChicagoStyleCheesePizza();
		} else if(type.compare("veggie") == 0){
			return pizza = new ChicagoStyleVeggiePizza();
		} else if(type.compare("clam") == 0){
			return pizza = new ChicagoStyleClamPizza();
		} else if(type.compare("pepperoni") == 0){
			return pizza = new ChicagoStylePepperoniPizza();
		} else {
            return pizza = NULL;
		}
	}
};
The main function is

int main(){
    NYPizzaStore nystore = NYPizzaStore();
    ChicagoPizzaStore cgstore = ChicagoPizzaStore();

    Pizza* nycheese = nystore.orderPizza("cheese");
    std::cout << "Ethan ordered a " << nycheese->getName() << std::endl;

    Pizza* cgcheese = cgstore.orderPizza("cheese");
    std::cout << "Ethan ordered a " << cgcheese->getName() << std::endl;

    return 0;
}


Abstract Factory method.  Abstract factory method is used to create a set of related products. Since one factory method is only able to generate one type of product, the abstract factory classaggregate several factory methods. Each factory method generate one type of product. The abstract factory is an abstract class. Its subclass generates different sets of products.

In order to implement abstract factory, the structure needs to be revised a little. We provide uniform treatment for ingredients. Then different stores can adjust for their special flavor.

class Cheese {
public:
    virtual ~Cheese() = 0 {}
	virtual std::string toString() const = 0;
};

class ReggianoCheese : public Cheese {
public:
    std::string toString() const { return "Reggiano Cheese"; }
};

class MozzarellaCheese : public Cheese {
public:
    std::string toString() const { return "Shredded Mozzarella"; }
};



class Dough {
public:
    virtual ~Dough() {}
	virtual std::string toString() const = 0;
};

class ThinCrustDough : public Dough {
public:
    std::string toString() const { return "Thin Crust Dough"; }
};

class ThickCrustDough : public Dough {
public:
    std::string toString() const { return "Thick Crust Dough"; }
};



class Sauce {
public:
    virtual ~Sauce() = 0 {}
	virtual std::string toString() const = 0;
};

class MarinaraSauce : public Sauce {
public:
    std::string toString() const { return "Marinara Sauce"; }
};

class PlumTomatoSauce : public Sauce {
public:
    std::string toString() const { return "Tomato sauce with plum tomatoes"; }
};



class Veggies {
public:
    virtual ~Veggies() = 0 {}
	virtual std::string toString() const = 0;
};

class Garlic : public Veggies {
public:
    std::string toString() const { return ("Garlic"); }
};

class Onion : public Veggies {
public:
    std::string toString() const { return ("Onion"); }
};

class Mushroom : public Veggies {
public:
    std::string toString() const { return ( "Mushrooms" ); }
};

class RedPepper : public Veggies {
public:
    std::string toString() const { return ( "Red Pepper" ); }
};



class Pepperoni {
public:
    virtual ~Pepperoni() = 0 {}
	virtual std::string toString() const = 0;
};

class SlicedPepperoni : public Pepperoni {
public:
    std::string toString() const { return "Sliced Pepperoni"; }
};




class Clams {
public:
    virtual ~Clams() = 0 {}
	virtual std::string toString() const = 0;
};

class FreshClams : public Clams {
public:
    std::string toString() const { return "Fresh Clams from Long Island Sound"; }
};

class FrozenClams : public Clams {
public:
    std::string toString() const { return "Frozen Clams from Chesapeake Bay"; }
};


class PizzaIngredientFactory{
public:
    virtual Dough* createDough() const = 0;
	virtual Sauce* createSauce() const = 0;
	virtual Cheese* createCheese() const = 0;
	virtual std::vector<Veggies*> createVeggies() const = 0;
	virtual Pepperoni* createPepperoni() const = 0;
	virtual Clams* createClam() const = 0;
	virtual ~PizzaIngredientFactory()= 0{}
};

class NYPizzaIngredientFactory : public PizzaIngredientFactory {
public:
    Dough* createDough() const { return new ThinCrustDough(); }
	Sauce* createSauce() const { return new MarinaraSauce(); }
 	Cheese* createCheese() const { return new ReggianoCheese(); }
 	std::vector< Veggies* > createVeggies() const {
		std::vector< Veggies* > veggies;
		veggies.push_back( new Garlic() );
		veggies.push_back( new Onion() );
		veggies.push_back( new Mushroom() );
		veggies.push_back( new RedPepper() );
		return veggies;
	}
 	Pepperoni* createPepperoni() const { return new SlicedPepperoni(); }
	Clams* createClam() const { return new FreshClams(); }
};

class ChicagoPizzaIngredientFactory : public PizzaIngredientFactory {
public:
    Dough* createDough() const { return new ThickCrustDough(); }
 	Sauce* createSauce() const { return new PlumTomatoSauce(); }
 	Cheese* createCheese() const { return new MozzarellaCheese(); }
 	std::vector< Veggies* > createVeggies() const {
		std::vector< Veggies* > value;
		value.push_back( new BlackOlives() );
		value.push_back( new Spinach() );
		value.push_back( new Eggplant() );
		return value;
	}
 	Pepperoni* createPepperoni() const { return new SlicedPepperoni(); }
	Clams* createClam() const { return new FrozenClams(); }
};
The pizza class has an abstract method prepare(), to combine various ingredients

class Pizza {
public:
    Dough* dough;
	Sauce* sauce;
	std::vector<Veggies*> veggies;
	Cheese* cheese;
	Pepperoni* pepperoni;
	Clams* clam;

	virtual void prepare() = 0;

	Pizza() {}
	virtual ~Pizza() {
		for(std::vector<Veggies*>::iterator iterator = veggies.begin(); veggies.end() != iterator; ++iterator ) {
			delete *iterator;
		}
		veggies.clear();
	}

	virtual void bake() const {
		std::cout << "Bake for 25 minutes at 350" << std::endl;
	}
	virtual void cut() const {
		std::cout << "Cutting the pizza into diagonal slices" << std::endl;
	}
	virtual void box() const {
		std::cout << "Place pizza in official PizzaStore box" << std::endl;
	}

	void setName( std::string name_) { name = name_; }
	std::string getName() const { return name; }

	void toString() const {
		std::cout << "---- " << _name.c_str() << " ----" << std::endl;

		if( dough.get() != 0 ) {
			std::cout << dough->toString();
			std::cout << std::endl;
		}
		if( sauce.get() != 0 ) {
			std::cout << sauce->toString();
			std::cout << std::endl;
		}
		if( cheese.get() != 0 ) {
			std::cout << cheese->toString();
			std::cout << std::endl;
		}
		if( clam.get() != 0 ) {
			std::cout << clam->toString();
			std::cout << std::endl;
		}
		if( pepperoni.get() != 0 ) {
			std::cout << pepperoni->toString();
			std::cout << std::endl;
		}
		if( veggies.size() != 0 ) {
			for(std::vector<Veggies*>::iterator iterator = veggies.begin(); veggies.end() != iterator; ++iterator ) {
				std::cout << (*iterator)->toString() << ", ";
			}
			std::cout << std::endl;
		}
	}

private:
    std::string name;
    Pizza(const Pizza& ); // Disable copy constructor
    void operator=(const Pizza& ); // Disable assignment operator
};

class CheesePizza : public Pizza {
private:
    PizzaIngredientFactory* ingredientFactory;

public:
    CheesePizza( PizzaIngredientFactory* ingredientFactory_ ) :
		ingredientFactory = ingredientFactory_;
	}

 	void prepare() {
		std::cout << "Preparing " << getName().c_str() << std::endl;
		dough = ingredientFactory->createDough();
		sauce = ingredientFactory->createSauce();
		cheese = ingredientFactory->createCheese();
	}
};

class ClamPizza : public Pizza {
private:
    PizzaIngredientFactory* ingredientFactory;

public:
	ClamPizza(PizzaIngredientFactory* ingredientFactory_){
        ingredientFactory = ingredientFactory_;
	}

	void prepare() {
		std::cout << "Preparing " << getName().c_str() << std::endl;
		dough = ingredientFactory->createDough();
		sauce = ingredientFactory->createSauce();
		cheese = ingredientFactory->createCheese();
		clam = ingredientFactory->createClam();
	}
};

class PepperoniPizza : public Pizza {
private:
    PizzaIngredientFactory* ingredientFactory;

public:
    PepperoniPizza(PizzaIngredientFactory* ingredientFactory ){
        ingredientFactory = ingredientFactory_;
    }

	void prepare() {
		std::cout << "Preparing " << getName().c_str() << std::endl;
		dough = ingredientFactory->createDough();
		sauce = ingredientFactory->createSauce();
		cheese = ingredientFactory->createCheese();
		pepperoni= ingredientFactory->createPepperoni();

		if(veggies.empty()){
            veggies = ingredientFactory->createVeggies();
		}
	}
};


class VeggiePizza : public Pizza {
private:
    PizzaIngredientFactory* ingredientFactory;

public:
	VeggiePizza(PizzaIngredientFactory* ingredientFactory){
        ingredientFactory = ingredientFactory_;
	}

	void prepare() {
		std::cout << "Preparing " << getName().c_str() << std::endl;
		dough = ingredientFactory->createDough();
		sauce = ingredientFactory->createSauce();
		cheese = ingredientFactory->createCheese();
		if(veggies.empty()){
			veggies = ingredientFactory->createVeggies();
		}
	}
};

The PizzaStore class is a factory, having a pure virtual function. The function take a another factory PizzaIngredientFactory as a parameter.

class PizzaStore {
public:
    PizzaStore() {}
    virtual ~PizzaStore() {}

	Pizza* orderPizza(std::string type) const {
		Pizza* pizza = createPizza(type);

		std::cout << "--- Making a " << pizza->getName() << " ---" << std::endl;
		pizza->prepare();
		pizza->bake();
		pizza->cut();
		pizza->box();
		return pizza;
	}

	virtual Pizza* createPizza(std::string type) const = 0;
};

class NYPizzaStore : public PizzaStore {
public:
    Pizza* createPizza(std::string item) const {
        Pizza* pizza = NULL;
        PizzaIngredientFactory* ingredientFactory = new NYPizzaIngredientFactory();

        if( item.compare( "cheese" ) == 0 ) {
            pizza = new CheesePizza(ingredientFactory);
            pizza->setName( "New York Style Cheese Pizza" );
        } else if( item.compare( "veggie" ) == 0 ) {
            pizza = new VeggiePizza(ingredientFactory);
            pizza->setName( "New York Style Veggie Pizza" );
        } else if(item.compare( "clam" ) == 0 ) {
            pizza = new ClamPizza( ingredientFactory );
            pizza->setName( "New York Style Clam Pizza" );
        } else if( item.compare( "pepperoni" ) == 0 ) {
            pizza = new PepperoniPizza( ingredientFactory );
            pizza->setName( "New York Style Pepperoni Pizza" );
        }

        return pizza;
	}
};

class ChicagoPizzaStore : public PizzaStore {
public:
    Pizza* createPizza(std::string item) const{
        Pizza* pizza = NULL;
        PizzaIngredientFactory* ingredientFactory = new NYPizzaIngredientFactory();

        if( item.compare( "cheese" ) == 0 ) {
            pizza = new CheesePizza( ingredientFactory );
            pizza->setName( "Chicago Style Cheese Pizza" );
        } else if( item.compare( "veggie" ) == 0 ) {
            pizza = new VeggiePizza( ingredientFactory );
            pizza->setName( "Chicago Style Veggie Pizza" );
        } else if( item.compare( "clam" ) == 0 ) {
            pizza = new ClamPizza( ingredientFactory );
            pizza->setName( "Chicago Style Clam Pizza" );
        } else if( item.compare( "pepperoni" ) == 0 ) {
            pizza = new PepperoniPizza( ingredientFactory );
            pizza->setName( "Chicago Style Pepperoni Pizza" );
        }

        return pizza;
	}
};
main function is

#include <iostream>
#include <./pizza_abstractfactory.hpp>
#include <./pizzastore_abstractfactory.h>
#include <./pizzaingredientfactory.hpp>
int main(){
    NYPizzaStore nystore = NYPizzaStore();
    ChicagoPizzaStore cgstore = ChicagoPizzaStore();

    Pizza* nycheese = nystore.orderPizza("cheese");
    std::cout << "Ethan ordered a " << nycheese->getName() << std::endl;

    Pizza* cgcheese = cgstore.orderPizza("cheese");
    std::cout << "Ethan ordered a " << cgcheese->getName() << std::endl;

    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值