工厂方法模式和抽象工厂模式

工厂方法模式和抽象工厂模式

工厂方法模式
#include <string>
#include <iostream>

// Abstract
class Splitter
{
private:
    /* data */
public:
    Splitter(/* args */);
    virtual ~Splitter();
public:
    virtual void split() = 0;
};

Splitter::Splitter(/* args */)
{
}

Splitter::~Splitter()
{
}

class BinarySplitter  : public Splitter
{
private:
    /* data */
public:
    BinarySplitter(/* args */);
    ~BinarySplitter();
    void split();
};

BinarySplitter::BinarySplitter(/* args */)
{
}

BinarySplitter::~BinarySplitter()
{
}

void BinarySplitter::split() {
    std::cout << "Binary split" << std::endl;
}

class TxtSplitter : public Splitter
{
private:
    /* data */
public:
    TxtSplitter(/* args */);
    ~TxtSplitter();
    void split();
};

TxtSplitter::TxtSplitter(/* args */)
{
}

TxtSplitter::~TxtSplitter()
{
}

void TxtSplitter::split() {
    std::cout << "Txt split"<< std::endl;
}

class PictureSplitter : public Splitter
{
private:
    /* data */
public:
    PictureSplitter(/* args */);
    ~PictureSplitter();
    void split();
};

PictureSplitter::PictureSplitter(/* args */)
{
}

PictureSplitter::~PictureSplitter()
{
}

void PictureSplitter::split() {
    std::cout << "Picture split" << std::endl;
}

class VideoSplitter : public Splitter
{
private:
    /* data */
public:
    VideoSplitter(/* args */);
    ~VideoSplitter();
    void split();
};

VideoSplitter::VideoSplitter(/* args */)
{
}

VideoSplitter::~VideoSplitter()
{
}

void VideoSplitter::split() {
    std::cout << "Video split" << std::endl;
}


#include <string>
#include "splitter.hpp"


// Factory 是一个工厂
class Factory
{
private:
    /* data */
public:
    Factory(/* args */);

    virtual Splitter* creat_splitter(std::string splitter) = 0;

    ~Factory();
};

Factory::Factory(/* args */)
{
}



Factory::~Factory()
{
}


Splitter* Factory::creat_splitter(std::string splitter) {
}

class TxtFactory : public Factory
{
private:
    /* data */
public:
    TxtFactory(/* args */);
    ~TxtFactory();
    Splitter* creat_splitter(std::string splitter);
};

TxtFactory::TxtFactory(/* args */)
{
}

TxtFactory::~TxtFactory()
{
}

Splitter* TxtFactory::creat_splitter(std::string splitter) {
    return new TxtSplitter();
}

class PictureFactory : public Factory
{
private:
    /* data */
public:
    PictureFactory(/* args */);
    ~PictureFactory();
    Splitter* creat_splitter(std::string splitter);
};

PictureFactory::PictureFactory(/* args */)
{
}

PictureFactory::~PictureFactory()
{
}

Splitter* PictureFactory::creat_splitter(std::string splitter) {
    return new PictureSplitter();
}


class VideoFactory : public Factory
{
private:
    /* data */
public:
    VideoFactory(/* args */);
    ~VideoFactory();
    Splitter* creat_splitter(std::string splitter);
};

VideoFactory::VideoFactory(/* args */)
{
}

VideoFactory::~VideoFactory()
{
}

Splitter* VideoFactory::creat_splitter(std::string splitter) {
    return new VideoSplitter();
}


class BinaryFactory : public Factory
{
private:
    /* data */
public:
    BinaryFactory(/* args */);
    ~BinaryFactory();
    Splitter* creat_splitter(std::string splitter);
};

BinaryFactory::BinaryFactory(/* args */)
{
}

BinaryFactory::~BinaryFactory()
{
}

Splitter* BinaryFactory::creat_splitter(std::string splitter) {
    return new BinarySplitter();
}


#include <iostream>
#include "splitter.hpp"
#include "splitter_factory.hpp"


class Mainform
{
private:
    Factory* factory_;
    /* data */
public:
    Mainform(Factory *factory);
    ~Mainform();
    Splitter* get_splitter();
};

Mainform::Mainform(Factory *factory) {
    factory_ = factory;
}

Mainform::~Mainform()
{
}

Splitter* Mainform::get_splitter() {
    return factory_->creat_splitter("xxx");
}
#include <iostream>
#include "splitter.hpp"
#include "splitter_factory.hpp"
#include "mainform.hpp"

int main()
{
    // 最外面使用的时候, 肯定是要创建一个具体的工厂类,然后把具体的工厂类提供给我们的对外接口类
    // 由这个对外接口类返回一个具体的产品 
    TxtFactory txtfactory;
    Mainform mainform(&txtfactory);
    Splitter* splitter = mainform.get_splitter();
    return 0;
}
抽象工厂模式
#include <vector>

// 第二
// 下面的函数中, 用到了三个具体类型, 根据这三个具体类型,我们就需要定义三个抽象类型
// 同时我们说,抽象工厂模式主要解决的问题是,需要创建一系列相关的对象,下面三个对象就是一系列相关的对象
class AbConnection
{
private:
    /* data */
public:
    AbConnection(/* args */);
    ~AbConnection();
};

AbConnection::AbConnection(/* args */)
{
}

AbConnection::~AbConnection()
{
}

class AbCommand
{
private:
    /* data */
public:
    AbCommand(/* args */);
    ~AbCommand();
};

AbCommand::AbCommand(/* args */)
{
}

AbCommand::~AbCommand()
{
}

class AbDataReader
{
private:
    /* data */
public:
    AbDataReader(/* args */);
    ~AbDataReader();
};

AbDataReader::AbDataReader(/* args */)
{
}

AbDataReader::~AbDataReader()
{
}



// 第三
// 下面函数中用到了三个具体类型,那么就需要定义三个具体的类型
// 支持Sql的数据库相关的类型
class SqlConnection : public AbConnection
{
private:
    /* data */
public:
    SqlConnection(/* args */);
    ~SqlConnection();
};

SqlConnection::SqlConnection(/* args */)
{
}

SqlConnection::~SqlConnection()
{
}

class SqlCommand : public AbCommand
{
private:
    /* data */
public:
    SqlCommand(/* args */);
    ~SqlCommand();
};

SqlCommand::SqlCommand(/* args */)
{
}

SqlCommand::~SqlCommand()
{
}

class SqlDataReader : public AbDataReader
{
private:
    /* data */
public:
    SqlDataReader(/* args */);
    ~SqlDataReader();
};

SqlDataReader::SqlDataReader(/* args */)
{
}

SqlDataReader::~SqlDataReader()
{
}



// 支持Oracle的数据库相关类型
class OracleConnection : public AbConnection
{
private:
    /* data */
public:
    OracleConnection(/* args */);
    ~OracleConnection();
};

OracleConnection::OracleConnection(/* args */)
{
}

OracleConnection::~OracleConnection()
{
}

class OracleCommand : public AbCommand
{
private:
    /* data */
public:
    OracleCommand(/* args */);
    ~OracleCommand();
};

OracleCommand::OracleCommand(/* args */)
{
}

OracleCommand::~OracleCommand()
{
}

class OracleDataReader : public AbDataReader
{
private:
    /* data */
public:
    OracleDataReader(/* args */);
    ~OracleDataReader();
};

OracleDataReader::OracleDataReader(/* args */)
{
}

OracleDataReader::~OracleDataReader()
{
}




// // 第五步
// // 因为第四步的使用中,new的部分还有具体的类型,这个时候我们可以考虑先使用工厂模式进行实现,
// // 于是针对上面的三个抽象基类,需要定义三个抽象基类对应的三个抽象工厂

// class AbConnectionFactory
// {
// private:
//     /* data */
// public:
//     AbConnectionFactory(/* args */);
//     ~AbConnectionFactory();
//     virtual AbConnection* CreatConnection() = 0;
// };

// AbConnectionFactory::AbConnectionFactory(/* args */)
// {
// }

// AbConnectionFactory::~AbConnectionFactory()
// {
// }

// class AbCommandFactory
// {
// private:
//     /* data */
// public:
//     AbCommandFactory(/* args */);
//     ~AbCommandFactory();
//     virtual AbCommand* CreatCommand() = 0;
// };

// AbCommandFactory::AbCommandFactory(/* args */)
// {
// }

// AbCommandFactory::~AbCommandFactory()
// {
// }

// class AbDataReaderFactory
// {
// private:
//     /* data */
// public:
//     AbDataReaderFactory(/* args */);
//     ~AbDataReaderFactory();
//     virtual AbDataReader* CreatDataReader() = 0;
// };

// AbDataReaderFactory::AbDataReaderFactory(/* args */)
// {
// }

// AbDataReaderFactory::~AbDataReaderFactory()
// {
// }



// 第十步
// 既然三个工厂创建的三个产品之间是相互关联的,那我们就可以考虑,将三个工厂方法合并成一个工厂工厂方法
// 既然是三个工厂方法的基类合并成一个了,我们就实际是定义了一个抽象工厂
// 于是就可以把下面的三个工厂方法的基类给合并成一个,
// 我们就可以把第五步的三个工厂方法给改成一个



class AbDatabaseFactory
{
private:
    /* data */
public:
    AbDatabaseFactory(/* args */);
    ~AbDatabaseFactory();
    virtual AbConnection* CreatConnection() = 0;
    virtual AbCommand* CreatCommand() = 0;
    virtual AbDataReader* CreatDataReader() = 0;
};

AbDatabaseFactory::AbDatabaseFactory(/* args */)
{
}

AbDatabaseFactory::~AbDatabaseFactory()
{
}






// // 第六步 
// // 有了抽象工厂方法类之后, 就需要三个具体工厂方法类
// // 这里因为有Sql和Oracle,然后是三个类,所以需要六个具体的工厂方法类
// class SqlConnectionFactory : public AbConnectionFactory
// {
// private:
//     /* data */
// public:
//     SqlConnectionFactory(/* args */);
//     ~SqlConnectionFactory();
// };

// SqlConnectionFactory::SqlConnectionFactory(/* args */)
// {
// }

// SqlConnectionFactory::~SqlConnectionFactory()
// {
// }

// class SqlCommandFactory : public AbCommandFactory
// {
// private:
//     /* data */
// public:
//     SqlCommandFactory(/* args */);
//     ~SqlCommandFactory();
// };

// SqlCommandFactory::SqlCommandFactory(/* args */)
// {
// }

// SqlCommandFactory::~SqlCommandFactory()
// {
// }

// class SqlDataReader : public AbDataReaderFactory
// {
// private:
//     /* data */
// public:
//     SqlDataReader(/* args */);
//     ~SqlDataReader();
// };

// SqlDataReader::SqlDataReader(/* args */)
// {
// }

// SqlDataReader::~SqlDataReader()
// {
// }

// class OracleConnectionFactory : public AbConnectionFactory
// {
// private:
//     /* data */
// public:
//     OracleConnectionFactory(/* args */);
//     ~OracleConnectionFactory();
// };

// OracleConnectionFactory::OracleConnectionFactory(/* args */)
// {
// }

// OracleConnectionFactory::~OracleConnectionFactory()
// {
// }


// class OracleCommandFactory : public AbCommandFactory
// {
// private:
//     /* data */
// public:
//     OracleCommandFactory(/* args */);
//     ~OracleCommandFactory();
// };

// OracleCommandFactory::OracleCommandFactory(/* args */)
// {
// }

// OracleCommandFactory::~OracleCommandFactory()
// {
// }

// class OracleDataReaderFactory : public AbDataReaderFactory
// {
// private:


// public:
//     OracleDataReaderFactory(/* args */);
//     ~OracleDataReaderFactory();
// };

// OracleDataReaderFactory::OracleDataReaderFactory(/* args */)
// {
// }

// OracleDataReaderFactory::~OracleDataReaderFactory()
// {
// }


// 第十一步
// 同样的道理, 既然我三个工厂方法的基类已经合成一个了, 那么我的Sql的三个工厂方法,和Oracle的三个工厂方法也应该合成一个
// 于是可以把第六步中的内容修改如下


class SqlDatabaseFactory : public AbDatabaseFactory
{
private:
    /* data */
public:
    SqlDatabaseFactory(/* args */);
    ~SqlDatabaseFactory();

    AbConnection* CreatConnection();
    AbCommand* CreatCommand();
    AbDataReader* CreatDataReader();
};

SqlDatabaseFactory::SqlDatabaseFactory(/* args */)
{
}

SqlDatabaseFactory::~SqlDatabaseFactory()
{
}

AbConnection* SqlDatabaseFactory::CreatConnection() {
    return new SqlConnection();
}
AbCommand* SqlDatabaseFactory::CreatCommand() {
    return new SqlCommand();
}
AbDataReader* SqlDatabaseFactory::CreatDataReader() {
    return new SqlDataReader();
}




class OracleDatabaseFactory : public AbDatabaseFactory
{
private:
    /* data */
public:
    OracleDatabaseFactory(/* args */);
    ~OracleDatabaseFactory();

    AbConnection* CreatConnection();
    AbCommand* CreatCommand();
    AbDataReader* CreatDataReader();
};

OracleDatabaseFactory::OracleDatabaseFactory(/* args */)
{
}

OracleDatabaseFactory::~OracleDatabaseFactory()
{
}


AbConnection* OracleDatabaseFactory::CreatConnection() {
    return new OracleConnection();
}
AbCommand* OracleDatabaseFactory::CreatCommand() {
    return new OracleCommand();
}
AbDataReader* OracleDatabaseFactory::CreatDataReader() {
    return new OracleDataReader();
}



class EmployeeDAO
{
private:
    // // 第七步
    // // 因为需要在后面的函数中get_employees中,所以需要先定义三个抽象的工厂
    // // 用户在创建一个EmployeeDAO的时候, 在构造函数中,需要传入具体的三个工厂,用来初始化三个抽象工厂
    // AbConnectionFactory* ab_connection_factory;
    // AbCommandFactory* ab_command_factory;
    // AbDataReaderFactory* ab_datareader_factory;

    // 第十二步
    // 既然已经有了抽象工厂模式,这个时候就可以把第七步中的三个工厂合并成一个工厂了
    AbDatabaseFactory* ab_database_factory;

    // 第九步
    // 看看问题所在
    // 我们在实际使用中, 需要在main函数中,调用EmployeeDAO的构造函数,第七步中说了,实例化一个EmployeeDAO的时候
    // 需要传入三个具体的工厂,在构造函数中, 把上面三个抽象的工厂给实例化了
    // 那么我们传入的三个工厂必须是同一个类型的三个抽象工厂
    // 比如第一个工厂是Sql的,那么第二个工厂不能是Oracle的,因为在下面的一个函数的实际使用中,三个工厂做出来的实际对象
    // 三个具体对象之间是有直接关系的, 是相互依赖的
    


public:
    EmployeeDAO(/* args */);
    ~EmployeeDAO();
    std::vector<EmployeeDAO> get_employees();
};

EmployeeDAO::EmployeeDAO(/* args */)
{
}

EmployeeDAO::~EmployeeDAO()
{
}




// 第一
// 如下就是一系列相互依赖的对象
// 同时存在一个问题就是,如果下次变成了MySql或者Redis的时候,下面函数的整个实现都需要修改
// std::vector<EmployeeDAO> EmployeeDAO::get_employees() {
//     SqlConnection* connect = new SqlConnection();
//     connect->ConnectString = "xxx";

//     SqlCommand* command = new SqlCommand();
//     command->set_connection(connec);
//     command->CommandTxt = "xxx";

//     SqlDataReader* reader = command->ExecuteReader();
//     while (read->Read())
//     {
//         std::cout << "xxx" << std::endl;
//     }
    
// }

// // 第四步
// // 既然上面定义抽象类型了, 所以我们需要重新写第一中的内容, 把其中用到具体类型的地方, 都修改成使用抽象类型的对象

// std::vector<EmployeeDAO> EmployeeDAO::get_employees() {
//     AbConnection* connect = new SqlConnection();

//     connect->ConnectString = "xxx";

//     AbCommand* command = new SqlCommand();
//     command->set_connection(connec);
//     command->CommandTxt = "xxx";

//     AbDataReader* reader = command->ExecuteReader();
//     while (read->Read())
//     {
//         std::cout << "xxx" << std::endl;
//     }
    
// }


// // 第八步 
// // 因为上面在类内部定义了三个抽象的工厂指针,所以需要在函数里面使用抽象的工厂指针进行创建具体的产品

// std::vector<EmployeeDAO> EmployeeDAO::get_employees() {
//     AbConnection* connect = ab_connection_factory->CreatConnection();
//     connect->ConnectString = "xxx";

//     AbCommand* command = ab_command_factory->CreatCommand();
//     // 另外需要注意的点是,三个对象之间具有相关性,这个是抽象工厂方法的精髓所在,一定是一系列对象之间具有相关性 
//     command->set_connection(connec);
//     command->CommandTxt = "xxx";

//     AbDataReader* reader = command->ExecuteReader();
//     while (read->Read())
//     {
//         std::cout << "xxx" << std::endl;
//     }
    
// }

// 第十三步
// 我们有了一个三合一的抽象工厂,那么这个时候就可以把第八步的内容给修改了
// 当然在定义这个类,EmployeeDAO的时候, 我们还是需要传入一个子类 抽象工厂 的,比如SqlDatabaseFactory

std::vector<EmployeeDAO> EmployeeDAO::get_employees() {
    AbConnection* connect = ab_database_factory->CreatConnection();
    connect->ConnectString = "xxx";

    AbCommand* command = ab_database_factory->CreatCommand();
    // 另外需要注意的点是,三个对象之间具有相关性,这个是抽象工厂方法的精髓所在,一定是一系列对象之间具有相关性 
    command->set_connection(connec);
    command->CommandTxt = "xxx";

    AbDataReader* reader = command->ExecuteReader();
    while (read->Read())
    {
        std::cout << "xxx" << std::endl;
    }
    
}

总结:

工厂方法模式:
一般用于我们需要根据不通的情况创建不同的产品, 为了让客户调用的时候不用依赖具体的类,使用工厂方法模式, 一般需要创建创建四组类:
第一种: 抽象产品类 Product
第二种:具体产品类,其父类是Product,具体产品类可以是ProductA,ProductB
第三种:抽象工厂方法类 AbFactory,他提供了一个接口CreateProduct,用于创建产品Product
第四种:具体工厂方法类,其父类是AbFactory,具体工厂方法类可以是FactoryA, FactoryB…,FactoryA和FactoryB都需要实现从父类集成来的CreateProduct,只不过FactoryA返回的是ProductA, FactoryB返回的是ProductB
用户在使用的过程中,大概用法如下:
第一步定义自己需要具体工厂比如FactoryA fa,
第二步调用fa的CreateProduct方法,获取具体子类ProductA

抽象工厂模式:用于解决需要创建一系列相互依赖的对象, 重点是解决相互依赖
我们可以先使用工厂方式模式解决这个问题,这里也需要四组类型
第一种: 抽象产品类 Product
第二种:具体产品类,其父类是Product,具体产品类可以是ProductA,ProductB
我们这里可能还有其他抽象类,比如Goods,和上面类似, 需要父类Goods, 和子类GoodsA, GoodsB
第三种:工厂方法父类ProductFactory,GoodsFactory,分别提供CreateProduct和CreateGoods
第四种:具体的工厂方法类ProductFactoryA, ProductFactoryB,GoodsFactoryA, GoodsFactoryB
在使用的时候考虑这样子一种使用场景, 我们可以利用ProductFactoryA和GoodsFactoryA创建ProductA,和GoodsA,并且ProductA和GoodsA是相互相关的, 那么用户在使用的过程中, 可能出现如下问题, 创建了ProductA和GoodsB,使用上就会出现错误,
于是我们把上面的第三种和第四种类型改动一下,第三种类型中, 我们把工厂(ProductFactory和GoodsFactory)合二为一变成ThingsFactory, 他提供提供了两个方法 CreateProduct和CreateGoods
第四种实现具体的工厂, ThingsFactoryA在实现CreateProduct和CreateGoods时分别返回 ProductA和GoodsA, 同理ThingsFactoryB
用户使用的时候:
第一步,定义自己具体需要的抽象工厂 ThingsFactoryA tfa;
Product pa = tfa.CreateProduct()
Goods ga = tfa.CreateGoods()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值