工厂模式

在前面的策略模式中Duck duck = new MallardDuck,new的是一个具体类—-用的是实现,而不是接口。∴会导致代码脆弱,缺乏弹性。
如果使用下面形式:

Duck duck;
if(picnic)    duck =  new MallardDuck();
else if(hunting)    duck = new DecoyDuck();
else if(inBathTub)  duck = RubberDuck();

需要在运行时,才能确定初始化的到底是哪一个类。一旦有变化或扩展,就必须对这段代码进行维护。
类设计原则:对扩展开放,对修改关闭。就需要找到变化的地方,把他们从不变的部分分离出来
如披萨店订购披萨:

Pizza pizza = new Pizza();

为了让系统有弹性,我们希望Pizza类是一个抽象类,但是抽象类是不能被实例化的—-只能作为指针类型使用。所以就需要指定特定类型的披萨: Pizza.orderPizza("PizzaType")。在orderPizza 函数中,根据传入的参数,new一个特定的Pizza子类,如:CheesePizza
但是,当菜单发生变化,增加或者删除特定类型的披萨时,就需要对orderPizza 函数中的一系列if...else 语句进行修改。
在类中,订购披萨的部分(new 语句)是变化的部分,所以将其修改为:

Pizza orderPizza(int type){
    Pizza pizza;

    // 变化部分:[根据传入的Pizza类型, new一个特定的Pizza子类] 

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

被搬出的代码,被放入一个特定职能的类中—-SimplePizzaFactory
简单披萨工厂(SimplePizzaFactory)为我们处理创建对象的细节,orderPizza变成了客户。需要披萨时候,就叫工厂做(new SpecficPizza())一个。orderPizza() 在得到一个Pizza之后,就可以、烘烤、切片、装合。
披萨风味:

enum PizzaType{cheese, pepperoni, clam, veggie};

披萨工厂:

class SimeplePizzaFactory
{
public:
    Pizza * createPizza(int type){
        if(type == int(PizzaType::cheese ))
        {
            return new CheesePizza();
        }
        else if(type == (PizzaType::clam))
        {
            return new ClamPizza();
        }
        return new Pizza();
    }
}

披萨店铺

class PizzaStore
{
private:
    SimplePizzaFactory *factory;
public:
    PizzaStore(SimplePizzaFactory *factory)
    {
        this->factory = factory;
    }
    Pizza * orderPizza(int type)
    {
        Pizza * pizza;
        pizza = factory->createPizza(type);
        // 对来自工厂的生披萨执行出售前的操作。
        // pizza.prepare();    pizza.bake();
        // pizza.cut();        pizza.box();
        return pizza;
    }
};
#include<iostream>
using namespace std;

enum PizzaType{cheese, pepperoni, veggie};

class Pizza{
public: 
    void bake(){ cout << "baking..." <<endl; };
};

class PepperoniPizza : public Pizza{        // 青椒
public:
    PepperoniPizza(){
        cout << "pepperoni Pizza"<<endl;
    }
};

class CheesePizza: public Pizza{            // 奶酪
public:
    CheesePizza(){
        cout << "Cheese Pizza"<<endl;
    }
};

class SimplePizzaFactory        // 披萨工厂
{
public:
    Pizza * createPizza(int type){
        if(type == int(PizzaType::cheese )){
            return new CheesePizza();
        }
        else if(type == ( PizzaType::pepperoni)){
            return  new PepperoniPizza();
        }
        return new Pizza();
    }
};

class PizzaStore        // 披萨店铺
{
private:
    SimplePizzaFactory *factory;
public:
    PizzaStore(SimplePizzaFactory *factory){
        this->factory = factory;
    }
    Pizza * orderPizza(int type){
        Pizza * pizza;
        pizza = factory->createPizza(type);
        pizza->bake();
        return pizza;
    }
};

int main()
{
    SimplePizzaFactory *factory = new SimplePizzaFactory();

    PizzaStore *ps = new PizzaStore(factory);
    ps->orderPizza(PizzaType::cheese);
    ps->orderPizza(PizzaType::pepperoni);
}

这里写图片描述

假如地方商店,需要使用披萨店特有的bake()、cut()、box()方式,就需要在PizzaStore里,将烘烤、切片和装合等过程分离出来,保持类的弹性。

披萨加盟店:—-不同地域实体店 && 不同风味披萨
纽约的奶酪披萨、纽约的青椒披萨….芝加哥的奶酪披萨、芝加哥的青椒披萨…
这里写图片描述
每个实体店的烘烤手法:
这里写图片描述
虽然说,“顾客”想要某种地域风味的披萨,由顾客决定——去某个实体店(NYSytlePizzaStore、ChicagoStylePizzaStore),在实体店内,订购各种风味的披萨。但是,实际上披萨的订购是实体店工厂之间的订购,披萨店决定是否给顾客想要的披萨。

纽约风味披萨——纽约披萨店:

class NYPizzaStore : public PizzaStore
{
    Pizza * createPizza(int type)
    {
        if( type == int(PizzaType::cheese) )
            return new NYStyleCheesePizza();    // 纽约风味奶酪披萨
        else if( type == int(PizzaType::pepperoni) )
            return new NYStylePepperoniPizza ();  // 纽约风味青椒披萨
        else 
            return nullptr;
    }
}

芝加哥风味披萨——芝加哥披萨店:

class ChicagoPizzaStore : public PizzaStore
{
    Pizza * createPizza(int type)
    {
        if( type == int(PizzaType::cheese) )
            return new ChicagoStyleCheesePizza();
        else if( type == int(PizzaType::pepperoni) )
            return new ChicagoStylePepperoniPizza();
        else 
            return nullptr;
    }
}
#include<iostream>
#include<vector>
using namespace std;

enum PizzaType{cheese, pepperoni, veggie};

class Pizza{
private:
    string name;
protected:
    vector<string> toppings;
public:
    void prepare(){
        cout << "Preparing " + name << endl ;
        cout << "Tossing dough..."<< endl;
        cout << "Adding sauce..."<< endl;
        cout << "Adding toppings..."<< endl;

        for( int i=0; i<int(toppings.size()); ++i){
             cout << "   " << toppings[i] << endl;
        }
    }
    void bake(){ cout << "Bake for 25 minutes at 350" << endl ;}
    void cut(){ cout << "cutting the pizza into diagonal slices" << endl ;}
    void box(){ cout << "Place Pizza in official PizzaStore box" << endl ;}
public :
    void setName( string str){name = str;}
    string getName(){return name;}
};

// 披萨店铺
class PizzaStore
{
public:
    Pizza * orderPizza(int type){
        Pizza * pizza;
        pizza = createPizza(type);

        cout << "--- Making a " << pizza->getName() <<" --- " <<endl;

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

        return pizza;
    }
    // 实例化披萨方法,替换了前面的"工厂"。
    virtual Pizza * createPizza(int type)= 0;
    // virtual Product factoryMethod(string type);
    // 抽象工厂 ==> 子类用来处理对象的创建
    // Product 工厂方法必须返回一个产品
    // factoryMethod 工厂方法将超类中的代码(orderPizza)解耦,
    // 与实际创建具体产品的代码分割开来。
};

// 虽然得到的是同一块饼,但是对饼的操作不一样
class NYStyleCheesePizza : public Pizza{
public:
    NYStyleCheesePizza()
    {
        setName( "New York Sytle Cheese Pizza");
        toppings.push_back("Grated Reggiano Cheese");
    }
};
class NYStylePepperoniPizza : public Pizza{
public:
    NYStylePepperoniPizza()
    {
        setName(  "New York Sytle Pepperoni Pizza" );
        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 ChicagoStyleCheesePizza : public Pizza{
public:
    ChicagoStyleCheesePizza()
    {
        setName( "Chicago Sytle Cheese Pizza");
        toppings.push_back("Shredded Mozzarella Cheese");
    }
    void cut(){cout << "Cutting the pizza into square slices"<< endl; 
    }
};
class ChicagoStylePepperoniPizza : public Pizza{
public:
    ChicagoStylePepperoniPizza()
    {
        setName( "Chicago Sytle Pepperoni Pizza");
    }
    void cut(){cout << "Cutting the pizza into square slices"<< endl; 
    }
};

class NYPizzaStore : public PizzaStore
{
public:
    NYPizzaStore(){};
    Pizza * createPizza(int type)
    {
        if( type == int(PizzaType::cheese) )
        {
            return new NYStyleCheesePizza();
        }
        else if( type == int(PizzaType::pepperoni) )
        {
            return new NYStylePepperoniPizza();
        }
        return nullptr;
    }
};

class ChicagoPizzaStore : public PizzaStore
{
public:
    ChicagoPizzaStore(){}
    Pizza * createPizza(int type)
    {
        if( type == int(PizzaType::cheese) )
        {
            return new ChicagoStyleCheesePizza();
        }
        else if( type == int(PizzaType::pepperoni) )
        {
            return new ChicagoStylePepperoniPizza();
        }
        return nullptr;
    }
};
int main()
{
    // 纽约风味披萨
    NYPizzaStore* NYPS = new NYPizzaStore();
    ChicagoPizzaStore* CPS = new ChicagoPizzaStore();

    NYPS->orderPizza(PizzaType::cheese);
    CPS->orderPizza(PizzaType::pepperoni);
}

输出:

--- Making a New York Sytle Cheese Pizza ---
Preparing New York Sytle Cheese Pizza
Tossing dough...
Adding sauce...
Adding toppings...
   Grated Reggiano Cheese
Bake for 25 minutes at 350
cutting the pizza into diagonal slices
Place Pizza in official PizzaStore box
--- Making a Chicago Sytle Pepperoni Pizza --
Preparing Chicago Sytle Pepperoni Pizza
Tossing dough...
Adding sauce...
Adding toppings...
Bake for 25 minutes at 350
cutting the pizza into diagonal slices
Place Pizza in official PizzaStore box

工厂方法模式

通过让子类决定该创建的对象是什么,从而封装对象创建的过程。
这里写图片描述
这里写图片描述

平行层级:
这里写图片描述

工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类实例化推迟到子类。
这里写图片描述
它将产品的“实现”从“使用”中解耦,如果增加产品或者改变产品的实现,Creator并不会受到影响。
简单工厂 v.s. 工厂方法
简单工厂:把全部的事情在一个地方处理完了。
工厂方法:创建一个框架,让子类决定如何实现。如:工厂方法中,orderPizza()方法提供了一般的框架,以便创建披萨,orderPizza()方法依赖工厂方法创建具体类,并制造出实际的披萨。

设计原则:依赖抽象,不要依赖具体类—-不能让高层组件依赖低层组件,而且,不论高层还是底层组件,二者都应该依赖于抽象。
PizzaStore 是高层组件,披萨的实现是低层组件
依赖倒置原则(Dependency Inversion Principle):
从顶端开始,然后往下到具体类。所以,不让披萨店理会这些具体类,防止披萨店依赖这些具体类。所以,从披萨开始。
然后需要一个工厂将这些具体类取出披萨店。所以,不同的具体披萨就依赖于一个抽象,披萨店也依赖这个抽象。
几个指导方针帮助你遵循依赖倒置原则:
这里写图片描述

如果要控制原料生产:

class PizzaIngredientFactory
{
    virtual Dough * createDough()=0;
    virtual Sauce * createSauce()=0;
    virtual Cheese * createCheese()=0;
    virtual Pepperoni * createPepperoni()=0;
}

纽约原料工厂:

    class NYPizzaIngredientFactory : public PizzaIngredientFactory{
    Dough * createDough(){ return new ThinCrustDough(); }
    virtual Sauce * createSauce(){ return new MarinaraSauce(); }
    virtual Cheese * createCheese(){ return new ReggianoCheese() }
    virtual Pepperoni * createPepperoni(){ return new SlicedPepperoni(); }
}

Pizza就可以改为:

class Pizza{
private:
    string name;
protected:
    vector<string> toppings;
public:
    virtual void prepare();
    void bake(){ cout << "Bake for 25 minutes at 350" << endl ;}
    void cut(){ cout << "cutting the pizza into diagonal slices" << endl ;}
    void box(){ cout << "Place Pizza in official PizzaStore box" << endl ;}
public :
    void setName( string str){name = str;}
    string getName(){return name;}
};
class CheesePizza : public Pizza
{
    PizzaIngredientFactory * ingredientFactory;
    CheesePizza(PizzaIngredientFactory * ingredientFactory)
    {
        this->ingredientFactory = ingredientFactory;
    }
    void prepare()
    {
        cout << "Preparing " + name ;
        dough = ingredientFactory->createDough();
        sauce = ingredientFactory->createsauce();
        cheese = ingredientFactory->createcheese();     
    }
}

创建原料的工厂:

sauce = ingredientFactory->createSauce();

纽约披萨店:

class NYPizzaStore : public PizzaStore
{
    Pizza * createPizza(int item)
    {
        Pizza * pizza = nullptr;
        PizzaIngredientFactory * ingredientFactory = new PizzaIngredientFactory();
        if(item == PizzaStyle::cheese)
        {
            pizza = new CheesePizza(ingredientFactory);
            pizza.setName("New York Style Cheese Pizza");
        }
        // ...
        return pizza;
    }
}

这里写图片描述
抽象工厂制作原料;将代码从实际工厂解耦,以便在不同上下文中实现各种各样的工厂,制造出不同的产品。

抽象工厂

提供一个接口,用于创建相关或者依赖对象的家族,而不需要明确指定具体类。
允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产出的具体产品是什么。

这里写图片描述
这里写图片描述

展开阅读全文

没有更多推荐了,返回首页