【设计模式】工厂模式以及抽象工厂

.前言
在了解什么是工厂模式和抽象工厂前我们先讲一下简单工厂。

一、简单工厂
定义:定义一个创建对象的类,并由这个类来封装实例化对象的行为。即将某类及其衍生类都有另外一个类去实例返回。

举例:pizza工厂

假设有个基类Pizza,它有3个子类:chessPizza,PepperPizza,GreakPizza。我们可以通过一个工厂类(SimplePizzaFactory)去实例化这三个子类。

类图:
在这里插入图片描述
代码:
Pizza基类:

class Pizza
{
public:
    virtual void prepare()
    {
        cout << "it's just a pizza." << endl;
    }
};

基类其中的一个子类:

class CheesePizza:public Pizza
{
public:
    virtual void prepare()
    {
	    cout<< "it's a pizza with cheese!" << endl;
    }
};

简单工厂类:

class SimplePizzaFactory
{
public:
    Pizza* CreatePizza(string ordertype)
    {
        Pizza* pizza = nullptr;
        if(ordertype=="cheese")
        {
            pizza = new CheesePizza();
        }
        else if(ordertype=="pepper")
        {
            pizza = new PepperPizza();
        }
        else if(ordertype=="greek")
        {
            pizza = new GreekPizza();
        }
        return pizza;
    }
};

主调函数:

int main()
{
    SimplePizzaFactory factory;
    Pizza *pizza=factory.CreatePizza("cheese");
    pizza->prepare();
    delete pizza;
    cout << "___________________________" << endl;
    pizza = factory.CreatePizza("pepper");
    pizza->prepare();
    delete pizza;
    cout << "___________________________" << endl;
    pizza = factory.CreatePizza("greek");
    pizza->prepare();
    delete pizza;
}

结果:

it's a pizza with cheese!
___________________________
it's a pizza with pepper!
___________________________
it's a pizza with greek!

从这里便可以看出,所谓“工厂”,就是被赋予某类的实例化的职责,使类的创建高度依赖工厂类。
这样便导致当我们想去拓展或修改程序,就需要多次修改此类,这显然违背了开闭原则,即当有新的功能时,尽量不要去修改某类,而是去新添别的类。
因此,我们可以建立一个负责实例的抽象方法,使新增的功能通过新的子类继承去实现。

二、工厂方法模式
**定义:**定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。

**举例:**我们依旧使用披萨的例子,只不过现在不再只有一家披萨店了,而是有伦敦和纽约两家产地的披萨店。

类图:
在这里插入图片描述

代码:
抽象工厂:

class OrderPizza
{
public:
    virtual Pizza CreatePizza() = 0;
};

两个产地的工厂

//伦敦披萨工厂
class LDOrderPizza:public OrderPizza
{
public:
    virtual Pizza* CreatePizza(string ordertype)
    {
        Pizza* pizza = nullptr;
	    if(ordertype=="cheese")
	    {
            pizza = new LDCheesePizza();
	    }
        else if(ordertype=="pepper")
        {
            pizza = new LDPepperPizza();
        }
	    else
	    {
            pizza = new LDGreekPizza();
	    }

        return pizza;
    }
};
//纽约披萨工厂
class NYOrderPizza :public OrderPizza
{
public:
    virtual Pizza* CreatePizza(string ordertype)
    {
        Pizza* pizza = nullptr;
        if (ordertype == "cheese")
        {
            pizza = new NYCheesePizza();
        }
        else if (ordertype == "pepper")
        {
            pizza = new NYPepperPizza();
        }
        else
        {
            pizza = new NYGreekPizza();
        }

        return pizza;
    }
};

pizza族因为无太多变化就不写了。

主调函数:

int main()
{
    //选择伦敦pizza工厂
    OrderPizza* factory = new LDOrderPizza();
    Pizza *pizza=factory->CreatePizza("cheese");
    pizza->prepare();
    delete pizza;
    cout << "____________________" << endl;
    pizza = factory->CreatePizza("pepper");
    pizza->prepare();
    delete pizza;
    cout << "____________________" << endl;
	delete factory;

    //选择纽约工厂
    factory = new NYOrderPizza();
    pizza = factory->CreatePizza("cheese");
    pizza->prepare();
    delete pizza;
    cout << "____________________" << endl;
    pizza = factory->CreatePizza("pepper");
    pizza->prepare();

    delete pizza;
    delete factory;
}

结果:

it's a pizza with cheese and it is from London!
____________________
it's a pizza with pepper and it is from London!
____________________
it's a pizza with cheese and it is from New York!
____________________
it's a pizza with pepper and it is from New York!

问题提出:
此时需要多添加一个产地,北京,则需要建立一个北京工厂继承OrderPizza,同时创建对应的Pizza即可。

代码:

class BJOrderPizza :public OrderPizza
{
public:
    virtual Pizza* CreatePizza(string ordertype)
    {
        Pizza* pizza = nullptr;
        if (ordertype == "cheese")
        {
            pizza = new BJCheesePizza();
        }
        else if (ordertype == "pepper")
        {
            pizza = new BJPepperPizza();
        }
        else
        {
            pizza = new BJGreekPizza();
        }

        return pizza;
    }
};

像这样,当需要增加新的功能时,可以在不修改原有类的基础上通过直接添加新类完成功能,拥有较好的拓展性。

提出问题:
披萨店怎么可以只有pizza?pizza要吃,煎饼果子也要吃,这样才能算得上健全!

上述的工厂方法模式只负责一种类的实例化,当一个工厂需要负责多种类的实例时,此时要使用的是抽象工厂。

三、抽象工厂模式
**定义:**定义一个实例多个类的抽象类,并由其子类去完成实例。

举例:现在全球突然兴起了吃煎饼果子,每家披萨店都开始也有卖煎饼果子了。

用例图:
在这里插入图片描述

代码:
披萨类:

class Pizza
{
public:
    virtual void prepare() = 0;
};

class LDCheesePizza:public Pizza
{
public:
    void prepare()
    {
        cout << "it's a pizza with cheese and from Lundon!" << endl;
    }
};

class LDPepperPizza :public Pizza
{
public:
    void prepare()
    {
        cout << "it's a pizza with pepper and from Lundon!" << endl;
    }
};

class NYCheesePizza :public Pizza
{
public:
    void prepare()
    {
        cout << "it's a pizza with cheese and from New York!" << endl;
    }
};

class NYPepperPizza :public Pizza
{
public:
    void prepare()
    {
        cout << "it's a pizza with pepper and from New York!" << endl;
    }
};

煎饼果子类:

class JianBingGuoZi
{
public:
    virtual void prepare() = 0;
};

class LDJianDanJBGZ :public JianBingGuoZi
{
public:
    void prepare()
    {
        cout << "来个伦敦地方味的煎饼果子!加个蛋儿!" << endl;
    }
};

class LDFangCongJBGZ :public JianBingGuoZi
{
public:
    void prepare()
    {
        cout << "来个伦敦地方味的煎饼果子!多放葱!" << endl;
    }
};

class NYJianDanJBGZ :public JianBingGuoZi
{
public:
    void prepare()
    {
        cout << "来个纽约地方味的煎饼果子!加个蛋儿!" << endl;
    }
};

class NYFangCongJBGZ :public JianBingGuoZi
{
public:
    void prepare()
    {
        cout << "来个纽约地方味的煎饼果子!多放葱!" << endl;
    }
};

工厂类:

class PizzaHouse
{
public:
    virtual Pizza* CreatePizza(string ordertype) = 0;
    virtual JianBingGuoZi* CreateJBGZ(string ordertype) = 0;
};

class LDPizzaHouse:public PizzaHouse
{
public:
    Pizza* CreatePizza(string ordertype)
    {
        Pizza* pizza = nullptr;
        if(ordertype=="cheese")
        {
            pizza = new LDCheesePizza();
        }
        else
        {
            pizza = new LDPepperPizza();
        }
        return pizza;
    }
    JianBingGuoZi* CreateJBGZ(string ordertype)
    {
        JianBingGuoZi* jbgz = nullptr;
        if(ordertype=="jiandan")
        {
            jbgz = new LDJianDanJBGZ();
        }
        else
        {
            jbgz = new LDFangCongJBGZ();
        }
        return jbgz;
    }
};

class NYPizzaHouse :public PizzaHouse
{
public:
    Pizza* CreatePizza(string ordertype)
    {
        Pizza* pizza = nullptr;
        if (ordertype == "cheese")
        {
            pizza = new NYCheesePizza();
        }
        else
        {
            pizza = new NYPepperPizza();
        }
        return pizza;
    }
    JianBingGuoZi* CreateJBGZ(string ordertype)
    {
        JianBingGuoZi* jbgz = nullptr;
        if (ordertype == "jiandan")
        {
            jbgz = new NYJianDanJBGZ();
        }
        else
        {
            jbgz = new NYFangCongJBGZ();
        }
        return jbgz;
    }
};

主调函数:

int main()
{
    //选择伦敦披萨屋
    PizzaHouse *pizza_house = new LDPizzaHouse();
    //叫pizza
    Pizza* pizza = pizza_house->CreatePizza("cheese");
    pizza->prepare();
    delete pizza;
    cout << "___________________________" << endl;
    pizza = pizza_house->CreatePizza("pepper");
    pizza->prepare();
    delete pizza;
    cout << "___________________________" << endl;
    //叫煎饼果子
    JianBingGuoZi* jbgz = pizza_house->CreateJBGZ("jiandan");
    jbgz->prepare();
    delete jbgz;
    cout << "___________________________" << endl;
    jbgz = pizza_house->CreateJBGZ("fangcong");
    jbgz->prepare();
    delete jbgz;
    cout << "___________________________" << endl;

    //选择纽约披萨屋
    pizza_house = new NYPizzaHouse();
    //叫pizza
    pizza = pizza_house->CreatePizza("cheese");
    pizza->prepare();
    delete pizza;
    cout << "___________________________" << endl;
    pizza = pizza_house->CreatePizza("pepper");
    pizza->prepare();
    delete pizza;
    cout << "___________________________" << endl;
    //叫煎饼果子
    jbgz = pizza_house->CreateJBGZ("jiandan");
    jbgz->prepare();
    delete jbgz;
    cout << "___________________________" << endl;
    jbgz = pizza_house->CreateJBGZ("fangcong");
    jbgz->prepare();
    delete jbgz;
    cout << "___________________________" << endl;
}

结果:

it's a pizza with cheese and from Lundon!
___________________________
it's a pizza with pepper and from Lundon!
___________________________
来个伦敦地方味的煎饼果子!加个蛋儿!
___________________________
来个伦敦地方味的煎饼果子!多放葱!
___________________________
it's a pizza with cheese and from New York!
___________________________
it's a pizza with pepper and from New York!
___________________________
来个纽约地方味的煎饼果子!加个蛋儿!
___________________________
来个纽约地方味的煎饼果子!多放葱!
___________________________

四、总结:
4.1、优缺点分析
由上述例子可以看到,无论是工厂方法还是抽象工厂,在原有的代码基础上,再增加一个产品工厂(产品等级)是很方便的;
一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象(将一个系列的产品统一一起创建);

但是,假如我们想要使工厂多增加一个产品类型时(比如现在披萨屋还要卖拉面),那么,除了要写新增加的产品类型以及其衍生类外,还要在原有代码基础上,修改抽象工厂以及其衍生工厂中的代码,增加实例新类的方法,这违背了开放封闭原则。
这使得产品族扩展非常困难,要增加一个系列的某一产品,既要修改工厂抽象类里加代码,又修改具体的实现类里面加代码;
同时增加了系统的抽象性和理解难度;

4.2、适用场景
一系列相关产品对象(属于同一产品族)一起创建时需要大量的重复代码;
提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体的实现;

4.3抽象工厂模式符合依赖抽象原则

1、创建对象实例时,不要直接 new一个对象, 而是把创建对象的动作放在一个工厂的方法中;

2、不要让类继承具体类,而是继承抽象类或者是实现接口;

3、不要覆盖基类中已经实现的方法;

附:工厂方法与抽象工厂的异同
工厂模式:定义一个用于创建对象的借口,让子类决定实例化哪一个类

抽象工厂模式:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类

个人觉得这个区别在于产品,如果产品单一,最合适用工厂模式,但是如果有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。再通俗深化理解下:工厂模式针对的是一个产品等级结构 ,抽象工厂模式针对的是面向多个产品等级结构的。

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值