【HeadFirst 设计模式】工厂模式的C++实现

简单工厂模式

一、案例背景

你是小镇上最有名的一家披萨店的店主,你们店里的披萨广受人们喜爱。你们的订单系统是这么写的:

Pizza* orderPizza(string type)
{
    Pizza* pizza {};

    if (type == "cheese")
    {
        pizza = new CheesePizza();
    }
    else if (type == "greek")
    {
        pizza = new greekPizza();
    }
    else if (type == "pepperoni")
    {
        pizza = new PepperoniPizza();
    }

    pizza.prepare();
    pizza.bake();
    pizza.cut();
    pizza.box();

    return pizza;
}

二、案例分析

看起来很正常。但是压力来自于增加更多的披萨类型。你发现你所有的竞争者都已经在他们的菜单中加入了一些流行风味的披萨,很明显,你必须要赶上他们,所以你也要将这些类型的披萨加进你的菜单中,而最近Greek Pizza卖的不好,所以你决定将它从菜单中去掉。

#include <iostream>
#include <string>
using namespace std;

Pizza* orderPizza(string type)
{
    Pizza* pizza {};

    if (type == "cheese")
    {
        pizza = new CheesePizza();
    }
    //else if (type == "greek")
    //{
    //    pizza = new greekPizza();
    //}
    else if (type == "pepperoni")
    {
        pizza = new PepperoniPizza();
    }
    else if (type == "clam")
    {
        pizza = new ClamPizza();
    }
    else if (type == "veggie")
    {
        pizza = new VeggiePizza();
    }

    pizza.prepare();
    pizza.bake();
    pizza.cut();
    pizza.box();

    return pizza;
}

前面提到过一个“开闭原则”,很明显地,如果实例化“某些”具体类,将使orderPizza()出问题,而且也无法让orderPizza()对修改关闭,但是,现在我们已经知道哪些会改变,哪些不会改变,是时候使用封装了。

现在最好将创建对象移到orderPizza()之外,但是怎么做呢?要把创建披萨的代码移到另一个对象中,由这个新对象专职创建披萨。

三、代码分析

看了代码实现之后,你可能会想:简单工厂模式看起来“简单”了,简单的不像个设计模式。这样做有什么好处?似乎只是把问题搬到另一个对象里罢了,问题依然存在。别忘了,SimplePizzaFactory可以有很多客户,虽然目前只看到了订单系统对齐进行了调用,但是,可能还有其他类利用这个工厂获取披萨的价钱和描述。

class SimplePizzaFactory
{
public:
    Pizza* createPizza(const String& type)
    {
        Pizza* pizza {};

        if (type == "cheese")
        {
            pizza = new CheesePizza();
        }
        else if (type == "greek")
        {
            pizza = new greekPizza();
        }
        else if (type == "pepperoni")
        {
            pizza = new PepperoniPizza();
        }
        else if (type == "clam")
        {
            pizza = new ClamPizza();
        }
        else if (type == "veggie")
        {
            pizza = new VeggiePizza();
        }

        return pizza;
    }
};
Pizza* orderPizza(string type)
{
    Pizza* pizza = SimplePizzaFactory().createPizza(type);

    pizza->prepare();
    pizza->bake();
    pizza->cut();
    pizza->box();

    return pizza;
}

工厂方法模式

一、案例背景

你的披萨店经营有成,击败了竞争者,现在大家都希望加盟你的店。身为加盟公司的经营者,你希望确保加盟店营运的质量,所以希望这些店都使用你那些经得起时间考验的代码。

在这个过程中,你发现加盟店的确是采用你的工厂创建披萨,但是其他部分,却开始采用他们自己根据当地人的口味做的一些改良:烘焙手法有些差异等等。再想想这个问题,你真的希望能够建立一个框架,把加盟店和创建披萨捆绑在一起的同时又保持一定的弹性。

二、案例分析

如果你已经学习过之前的设计模式,想必一定已经对面向接口编程有了一定的理解。既然我们想要根据不同的披萨店定制个性化的披萨,那就简单干脆一些,写出一个工厂父类,然后实现好几个具体工厂继承它,这样在创建的时候我们便能够动态的选择不同的工厂去制作披萨。

这样做确实可以,但是从不同的工厂获取原材料就意味着你对披萨的质量失去了一定的控制。这里提出另外一种做法:将工厂不再抽象为一个接口,而是抽象为一个方法,由这个方法获得具体的披萨实例。代码轮廓大概是这样的:

class PizzaStore
{
public:
    pizza orderPizza(const String& type)
    {
        Pizza pizza = createPizza(type);

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();

        return pizza;
    }
    virtual Pizza createPizza(const string& type) const = 0;
};

然后由具体的子类继承并实现自己需要的createPizza接口,这样一来,顾客决定到哪一家披萨店下订单才决定了披萨的风味。

三、代码分析

这里给出工厂方法模式的相关案例:

#include <iostream>
#include <string>
using namespace std;

class Pizza
{   // 这里省略具体细节
public:
    void prepare() {}
    void bake() {}
    void cut() {}
    void box() {}
};

class NYStylePizza : public Pizza
{
};
class NYStyleVeggiePizza : public Pizza
{
};
class NYStylePepperoniPizza : public Pizza
{
};

class ChicagoStylePizza : public Pizza
{
};
class ChicagoStyleVeggiePizza : public Pizza
{
};
class ChicagoStylePepperoniPizza : public Pizza
{
};

class PizzaStore
{
public:
    Pizza* orderPizza(const string& type)
    {
        Pizza* pizza = createPizza(type);

        pizza->prepare();
        pizza->bake();
        pizza->cut();
        pizza->box();

        return pizza;
    }
    virtual Pizza* createPizza(const string& type) const = 0;
};

class NYPizzaStore : public PizzaStore
{
    Pizza* createPizza(const string& type) const override
    {
        if (type == "cheese")
        {
            return new NYStylePizza();
        }
        else if (type == "veggie")
        {
            return new NYStyleVeggiePizza();
        }
        else if (type == "clam")
        {
            return new NYStylePepperoniPizza();
        }
        else
        {
            return nullptr;
        }
    }
};

class ChicagoPizzaStore : public PizzaStore
{
    Pizza* createPizza(const string& type) const override
    {
        if (type == "cheese")
        {
            return new ChicagoStylePizza();
        }
        else if (type == "veggie")
        {
            return new ChicagoStyleVeggiePizza();
        }
        else if (type == "clam")
        {
            return new ChicagoStylePepperoniPizza();
        }
        else
        {
            return nullptr;
        }
    }
};

int main()
{
    // 定制一个纽约风味的披萨
    Pizza* NYStyle      = (new NYPizzaStore())->orderPizza("cheese");
    // 定制一个芝加哥风味的披萨
    Pizza* ChicagoStyle = (new ChicagoPizzaStore())->orderPizza("cheese");
    return 0;
}

抽象工厂模式

一、案例背景

现在,披萨店的加盟生意如火如荼,但是随着时间的流逝,一些加盟店开始使用低价的原材料来增加利润。你必须采取一些手段,以免长此以往砸了自己的招牌。

如何确保所有加盟店的原材料使用高质量的原材料呢?你打算建造一家生产原料的工厂,并将原材料送到各家加盟店。

二、案例分析

现在,我们要建造一个工厂来生产原料,这个工厂将负责创建原料家族的每一种原料。也就是说,工厂还需要生产面团,酱料等。

先为工厂定义一个接口,这个接口负责创建所有品类的原材料:

class PizzaIngredientFactory
{
public:
    virtual Dough*   createDough()   = 0;
    virtual Sauce*   createSauce()   = 0;
    virtual Cheese*  createCheese()  = 0;
    virtual Veggies* createVeggies() = 0;
    virtual Clams*   createClams()   = 0;
};

然后创建具体的工厂实现:

class NYPizzaIngredientFactory : public PizzaIngredientFactory
{
    Dough* createDough() override
    {
        return new ThinCrustDough();
    }
    Sauce* createSauce() override
    {
        return new MarinaraSauce();
    }
    Cheese* createCheese() override
    {
        return new ReggianoCheese();
    }
    Veggies* createVeggies() override
    {
        return new NYVeggies();
    }
    Clams* createClams() override
    {
        return new FreshClams();
    }
};

之后就是将这些工厂与原来的代码进行合并。

三、代码分析

这里给出抽象工厂模式的相关案例:

#include <iostream>
#include <string>
using namespace std;

class Dough
{
};
class ThinCrustDough : public Dough
{
};
class Sauce
{
};
class MarinaraSauce : public Sauce
{
};
class Cheese
{
};

class ReggianoCheese : public Cheese
{
};
class Veggies
{
};
class NYVeggies : public Veggies
{
};
class Clams
{
};
class FreshClams : public Clams
{
};

class PizzaIngredientFactory
{
public:
    virtual Dough*   createDough()   = 0;
    virtual Sauce*   createSauce()   = 0;
    virtual Cheese*  createCheese()  = 0;
    virtual Veggies* createVeggies() = 0;
    virtual Clams*   createClams()   = 0;
};

class NYPizzaIngredientFactory : public PizzaIngredientFactory
{
public:
    Dough* createDough() override
    {
        return new ThinCrustDough();
    }
    Sauce* createSauce() override
    {
        return new MarinaraSauce();
    }
    Cheese* createCheese() override
    {
        return new ReggianoCheese();
    }
    Veggies* createVeggies() override
    {
        return new NYVeggies();
    }
    Clams* createClams() override
    {
        return new FreshClams();
    }
};

class Pizza
{
protected:
    string   name    = nullptr;
    Dough*   dough   = nullptr;
    Sauce*   sauce   = nullptr;
    Cheese*  cheese  = nullptr;
    Veggies* veggies = nullptr;
    Clams*   clams   = nullptr;

public:
    virtual void prepare() = 0;
    void         bake() {}
    void         cut() {}
    void         box() {}

    string getName()
    {
        return name;
    }
    void setName(string name)
    {
        name = name;
    }
};

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

public:
    CheesePizza(PizzaIngredientFactory* factory) : factory(factory) {}
    void prepare() override   // 神奇的事情在这里发生
    {
        name    = "Cheese Pizza";
        dough   = factory->createDough();
        sauce   = factory->createSauce();
        cheese  = factory->createCheese();
        veggies = factory->createVeggies();
        clams   = factory->createClams();
    }
};

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

public:
    ClamPizza(PizzaIngredientFactory* factory) : factory(factory) {}
    void prepare() override   // ClamPizza的原料在这里拿到
    {
        name    = "Clam Pizza";
        cheese  = factory->createCheese();
        veggies = factory->createVeggies();
        clams   = factory->createClams();
    }
};

class PizzaStore
{
public:
    Pizza* orderPizza(const string& type)
    {
        Pizza* pizza = createPizza(type);

        pizza->prepare();
        pizza->bake();
        pizza->cut();
        pizza->box();

        return pizza;
    }
    virtual Pizza* createPizza(const string& type) const = 0;
};

class NYPizzaStore : public PizzaStore
{
public:
    Pizza* createPizza(const string& type) const override
    {
        Pizza*                  pizza           = nullptr;
        PizzaIngredientFactory* instanceFactory = new NYPizzaIngredientFactory();

        if (type == "cheese")
        {
            pizza = new CheesePizza(instanceFactory);
            pizza->setName("New York Style Cheese Pizz");
        }
        else if (type == "clam")
        {
            pizza = new ClamPizza(instanceFactory);
            pizza->setName("New York Style Clam Pizz");
        }

        return pizza;
    }
};

int main()
{
    // 定制一个纽约风味的披萨
    Pizza* NYStyle = (new NYPizzaStore())->orderPizza("cheese");
    return 0;
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值