工厂模式(简单工厂模式、工厂方法模式、抽象工厂模式)

        工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来, 达到提高灵活性的目的。

一、简单工厂模式

        简单工厂模式,它在的目的很简单:定义一个用于创建对象的接口。其构成如下:

1)工厂类角色

含有一定的逻辑判断,根据不同条件去生成不同的对象。

2)抽象产品角色

其一般为父类,提供抽象的接口

3)具体产品角色

继承与父类,在该类中提供产品的具体实现。

其类图展示如下:

代码实例1:

//---------factory.h
#ifndef FACTORY_H
#define FACTORY_H
#include "car.h"

// 抽象产品角色
class Factory
{
public:
    // 用于构建对象的接口
    Car* CreateCar(int type);
};

#endif // FACTORY_H

//---------factory.cpp
#include "factory.h"
#include "baoma.h"
#include "benchi.h"
#include <stddef.h>

Car* Factory::CreateCar(int type)
{
    Car* car = NULL;
    switch (type)
    {
    case 0:
        car = new BaoMa();
        break;
    case 1:
        car = new BenChi();
        break;
    default:
        break;
    }

    return car;
}

//---------car.h
#ifndef CAR
#define CAR

// 抽象产品类:Car
class Car
{
public:
    Car();

    // 接口Drive
    virtual void Drive();
    virtual ~Car();
};

#endif // CAR


//---------car.cpp
#include "car.h"
#include <iostream>

Car::Car()
{
    std::cout << "Car constructor." << std::endl;
}

Car::~Car()
{
    std::cout << "Car destructor." << std::endl;
}

void Car::Drive()
{
    std::cout << "Car Drive" << std::endl;
}

//---------benchi.h
#ifndef BENCHI
#define BENCHI
#include "car.h"
// 具体Car种类:奔驰
class BenChi : public Car
{
public:
    BenChi();
    ~BenChi();
    void Drive() override;
};

#endif // BENCHI


//---------benchi.cpp
#include "benchi.h"

#include <iostream>

using std::cout;
using std::endl;

BenChi::BenChi()
{
    cout << "BenChi constructor." << endl;
}

BenChi::~BenChi()
{
    cout << "BenChi destructor." << endl;
}

void BenChi::Drive()
{
    cout << "BenChi drive." << endl;
}

//---------baoma.h
#ifndef BAOMA
#define BAOMA
#include "car.h"

// 具体Car种类:宝马
class BaoMa : public Car
{
public:
    BaoMa();
    ~BaoMa();
    void Drive() override;
};

#endif // BAOMA


//---------baoma.cpp
#include "baoma.h"
#include <iostream>

using std::cout;
using std::endl;

BaoMa::BaoMa()
{
    cout << "BaoMa constructor." << endl;
}

BaoMa::~BaoMa()
{
    cout << "BaoMa destructor." << endl;
}

void BaoMa::Drive()
{
    cout << "BaoMa drive." << endl;
}

//---------main.cpp
#include <iostream>

using namespace std;
#include "factory.h"

int main()
{
    Factory factory;
    int type = 0;

    // 构建对象
    Car* car = factory.CreateCar(type);
    if (!car)
    {
        cout << "failed, exit." << endl;
        return 0;
    }

    // 执行动作
    car->Drive();

    delete car;
    car = NULL;
    return 0;
}
#--------CMakeLists.txt
project(test)
cmake_minimum_required(VERSION 2.8)
add_compile_options(-std=c++11)
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})


程序编译运行输出如下:

Car constructor.

BaoMa constructor.

BaoMa drive.

BaoMa destructor.

Car destructor.

通过使用简单工厂模式

1)客户端免除了直接创建产品对象的责任

2)如果需要增加一辆属于Car类型的车,比如法拉利,只需要通知工厂类添加该型号的车产生,然后再增加其具体车型的.cpp和.h文件就可以了。

对产品部分来说,它是符合开闭原则(对扩展开放;对修改关闭)的;但是工厂部分好像不太理想,因为
每增加一辆车,都要在工厂类中增加相应的业务逻辑或者判断逻辑,这显然是违背开闭原则
的。可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类(在我们的例子中

是为Factory),我们称它为全能类或者上帝类。

我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。
由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝累坏了,
也累坏了我们这些程序员,每多一款Car类型的车,都得把Factory修改一下,不是说好遵循开闭原则的嘛~

于是工厂方法模式作为救世主出现了。

二、工厂方法模式

工厂方法模式主要是将集中在Factory类创建对象的压力分摊到其多个子类Factory上,因而该模式的结构大致如下:

1)抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须
实现的接口或者必须继承的父类。

2)具体工厂角色:根据相关业务逻辑,创建具体的产品。

3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。

4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。

用类图来清晰的表示下的它们之间的关系:


工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。当有新款的Car需要产生时,只需要按照抽象工厂角色和抽象产品角色提供的规则去产生这款汽车即可,直接扩展而不用修改已经有的代码,这样也是遵循了开闭原则的。

代码实例2:

抽象产品角色和具体产品角色的代码和实例1,此处略过。

我们只需要去修改Factory类.h 和.cpp相关代码

//---------factory.h
#ifndef FACTORY_H
#define FACTORY_H
#include "car.h"

// 抽象产品角色
class Factory
{
public:
    // 用于构建对象的接口
    virtual Car* CreateCar() = 0;
    virtual ~Factory() {}
};

#endif // FACTORY_H

//---------baomafactory.h
#ifndef BAOMAFACTORY
#define BAOMAFACTORY

#include "factory.h"
#include <iostream>

// 宝马工厂子类
class BaoMaFactory : public Factory
{
public:
    Car* CreateCar() override;
    ~BaoMaFactory() { std::cout << "BaoMaFactory" << std::endl; }
};
#endif // BAOMAFACTORY

#include "baomafactory.h"
#include "baoma.h"


Car *BaoMaFactory::CreateCar()
{
    Car* car = new BaoMa();
    return car;
}
//---------benchifactory.h
#ifndef BENCHIFACTORY
#define BENCHIFACTORY
#include <iostream>

#include "factory.h"

// 奔驰工厂子类
class BenChiFactory : public Factory
{
public:
    Car* CreateCar() override;
    virtual ~BenChiFactory() { std::cout << "BenChiFactory destructor." << std::endl; }
};

#endif // BENCHIFACTORY

//-------benchifactory.cpp
#include "benchifactory.h"
#include "benchi.h"

Car* BenChiFactory::CreateCar()
{
    Car* car = new BenChi();
    return car;
}

//---------main.cpp
#include <iostream>

using namespace std;
#include "factory.h"
#include "baomafactory.h"
#include "benchifactory.h"

int main()
{
    // 根据需要构建指定的子类工厂
    Factory* pf = new BaoMaFactory();

    // 构建Car对象
    Car* car = pf->CreateCar();
    if (!car)
    {
        cout << "failed, exit." << endl;
        return 0;
    }

    // 执行动作
    car->Drive();

    delete car;
    car = NULL;

    delete pf;
    pf = NULL;
    return 0;
}

可以看出工厂方法的加入,使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。因为如果不能避免这种情况,可以考虑使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。

其实,简单工厂模式与工厂方法模式真正的避免了代码的改动了?没有。在简单工厂模式中,新产品的加入要修改工厂角色中的判断语句;而在工厂方法模式中,要么将判断逻辑留在抽象工厂角色中,要么在客户程序中将具体工厂角色写死(就象上面的例子一样),而且产品对象创建条件的改变必然会引起工厂角色的修改。

三、抽象工厂模式

抽象工厂模式就变得比工厂模式更为复杂,就像上面提到的缺点一样,工厂模式和简单工厂模式要求产品子类必须要是同一类型的,拥有共同的方法,这就限制了产品子类的扩展。于是为了更加方便的扩展,这里引入了产品族的概念。产品族即是位于不同产品等级结构中,功能相关联的产品组成的家族。让我们用下图来形象地说明一下:

图 中 的 BmwCar 和 BenzCar 就 是两 个 产 品 树 ( 产 品 层 次 结 构 ); 而 如 图 所 示 的
BenzSportsCar 和 BmwSportsCar 就是一个产品族。他们都可以放到跑车家族中,因此功能

有所关联。同理 BmwBussinessCar 和 BenzSportsCar 也是一个产品族。

回到我们的抽象工厂模式上,其相关类图如下:

ProductA1和ProductB1假设其为功能相关的,它们可以联系在一起,成为了一个产品族;ProductA2和ProductB2成为了另一个 产品族。

时间关系,实现代码暂时忽略。





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值