design_pattern_factory

来源:互联网 发布:超星尔雅网络登录页面 编辑:程序博客网 时间:2024/06/06 03:58

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 constructorvoid operator=(const Pizza& ); // Disable assignment operatorpublic: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
原创粉丝点击