设计模式之工厂模式(C++)

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

一、工厂模式是什么?

       工厂模式是一种创建型的软件设计模式。定义一个用于创建对象的工厂接口,并让工厂子类决定实例化哪一个产品类,使产品类的实例化延迟到工厂子类中执行。说白了就是用来造东西的,一般是比较简单的东西,我们不需要知道它如何生产的,直接从工厂拿到产品即可。

       工厂模式的优点:

  1. 良好的封装性。将产品的实例化封装执行,避免被修改,这样的产品具备良好的一致性。
  2. 良好的扩展性。增加产品时,同步增加一个工厂子类,不会违反开闭原则。
  3. 标准的解耦合框架。使用者只需要知道自己要什么产品即可,不用去管产品具体的特性等等,降低了模块间的耦合。

      工厂模式的缺点:

  1. 代码量大。每加一个产品,都要加一个工厂子类,代码会显得臃肿。
  2. 不利于扩展复杂的产品结构。如果你要苹果、香蕉、梨,工厂模式的结构还可以,但如果你要山东的苹果、海南的香蕉、北京的苹果,就显得结构呆呆的。这可以用抽象工厂模式解决,对产品族和产品种类进行区分。

二、简单工厂模式

       在介绍工厂模式前,先介绍其前身-简单工厂模式,简单工厂模式是用一个简单的工厂类,直接对产品进行实例化,虽然大大减少了代码量,但是违反了设计中的开闭原则,因为每次添加产品,工厂类都要进行修改。

2.1 结构图

       客户端即Main主函数,调用简单工厂制造产品,并获取产品。具体要什么产品由客户端命令决定。

 2.2 代码示例

       场景描述:我联系了一个生产水果的工厂,从工厂拿了一个苹果、一个香蕉和一个梨,用来果腹,工厂给我一个报价我付钱即可。

//Prodect.h
/****************************************************/
#pragma once
#include <iostream>

using namespace std;

// 产品种类
enum PRODECT_TYPE
{
	APPLE,                     // 苹果
	BANANA,					   // 香蕉
	PEAR					   // 梨
};

// 抽象产品类
class Prodect
{
public:
	// 构造函数
	Prodect(int price) :m_price(price) {};
	// 析构函数
	virtual ~Prodect() {};
	// 获取价格
	int getPrice() {
		return m_price;
	}
protected:
	// 产品价格
	int m_price;
};

// 具体产品类-苹果
class AppleProdect : public Prodect
{
public:
	// 构造函数
	AppleProdect(int price) :Prodect(price) {
		cout << "获得了一个苹果。" << endl;
	};
	// 析构函数
	virtual ~AppleProdect() {
		cout << "吃掉了一个苹果。" << endl;
	};
};

// 具体产品类-香蕉
class BananaProdect : public Prodect
{
public:
	// 构造函数
	BananaProdect(int price) :Prodect(price) {
		cout << "获得了一个香蕉。" << endl;
	};
	// 析构函数
	virtual ~BananaProdect() {
		cout << "吃掉了一个香蕉。" << endl;
	};
};

// 具体产品类-梨
class PearProdect : public Prodect
{
public:
	// 构造函数
	PearProdect(int price) :Prodect(price) {
		cout << "获得了一个梨。" << endl;
	};
	// 析构函数
	virtual ~PearProdect() {
		cout << "吃掉了一个梨。" << endl;
	};
};

//Factory.h
/****************************************************/
#pragma once
#include <iostream>
#include "Prodect.h"

using namespace std;

// 简单工厂
class SimpleFactory
{
public:
	// 获取产品
	Prodect* getProdect(PRODECT_TYPE type) {
		Prodect* prodect = nullptr;
		switch (type)
		{
		case APPLE:
			prodect = new AppleProdect(5);
			break;
		case BANANA:
			prodect = new BananaProdect(2);
			break;
		case PEAR:
			prodect = new PearProdect(3);
			break;
		default:
			cout << "无该产品。" << endl;
			break;
		}
		return prodect;
	}
};

//main.cpp
/****************************************************/
#include <iostream>
#include "Factory.h"
#include "Prodect.h"

using namespace std;

int main()
{
	SimpleFactory* factory = new SimpleFactory();
	cout << "开始生产。" << endl;
	Prodect *A = factory->getProdect(APPLE);
	Prodect *B = factory->getProdect(BANANA);
	Prodect *C = factory->getProdect(PEAR);
	int applePrice = A->getPrice();
	int bananaPrice = B->getPrice();
	int pearPrice = C->getPrice();
	int sum = A->getPrice() + B->getPrice() + C->getPrice();
	cout << "苹果价格:" << applePrice << "元。" << endl;
	cout << "香蕉价格:" << bananaPrice << "元。" << endl;
	cout << "梨子价格:" << pearPrice << "元。" << endl;
	cout << "累计消费:" << sum << "元。" << endl;
	delete A;
	delete B;
	delete C;
    delete factory;
	cout << "享用完毕。" << endl;
	return 0;
}

       程序结果如下。

        在上述示例中,我们可以看到,如果我想给工厂再添加一个产品,那么除了添加一个产品子类外,还要跑到简单工厂的类中进行switch的扩展,这样不利于代码的封装,破坏了开闭原则。而工厂模式的设计能弥补该不足。

三、工厂模式

3.1 结构图

       客户端即Main主函数,通过工厂子类来制造对应的产品,并获取产品。具体要什么产品由工厂子类决定。

 3.2 代码示例

       场景描述:我联系了一个生产水果的工厂,从工厂拿了一个苹果、一个香蕉和一个梨,用来果腹,工厂给我一个报价我付钱即可。

//Prodect.h
/****************************************************/
#pragma once
#include <iostream>

using namespace std;

// 抽象产品类
class Prodect
{
public:
	// 构造函数
	Prodect(int price) :m_price(price) {};
	// 析构函数
	virtual ~Prodect() {};
	// 获取价格
	int getPrice() {
		return m_price;
	}
protected:
	// 产品价格
	int m_price;
};

// 具体产品类-苹果
class AppleProdect : public Prodect
{
public:
	// 构造函数
	AppleProdect(int price) :Prodect(price) {
		cout << "获得了一个苹果。" << endl;
	};
	// 析构函数
	virtual ~AppleProdect() {
		cout << "吃掉了一个苹果。" << endl;
	};
};

// 具体产品类-香蕉
class BananaProdect : public Prodect
{
public:
	// 构造函数
	BananaProdect(int price) :Prodect(price) {
		cout << "获得了一个香蕉。" << endl;
	};
	// 析构函数
	virtual ~BananaProdect() {
		cout << "吃掉了一个香蕉。" << endl;
	};
};

// 具体产品类-梨
class PearProdect : public Prodect
{
public:
	// 构造函数
	PearProdect(int price) :Prodect(price) {
		cout << "获得了一个梨。" << endl;
	};
	// 析构函数
	virtual ~PearProdect() {
		cout << "吃掉了一个梨。" << endl;
	};
};

//Factory.h
/****************************************************/
#pragma once
#include <iostream>
#include "Prodect.h"

using namespace std;

// 抽象工厂类
class Factory
{
public:
	// 获取产品
	virtual Prodect* getProdect() = 0;
};

// 具体工厂类-苹果
class AppleFactory : public Factory
{
public:
	// 获取产品
	virtual Prodect* getProdect() {
		Prodect* prodect = new AppleProdect(5);
		return prodect;
	}
};

// 具体工厂类-香蕉
class BananaFactory : public Factory
{
public:
	// 获取产品
	virtual Prodect* getProdect() {
		Prodect* prodect = new BananaProdect(2);
		return prodect;
	}
};

// 具体工厂类-梨
class PearFactory : public Factory
{
public:
	// 获取产品
	virtual Prodect* getProdect() {
		Prodect* prodect = new PearProdect(3);
		return prodect;
	}
};

//main.cpp
/****************************************************/
#include <iostream>
#include "Factory.h"
#include "Prodect.h"

using namespace std;

int main()
{
	Factory* factoryA = new AppleFactory();
	Factory* factoryB = new BananaFactory();
	Factory* factoryC = new PearFactory();
	cout << "开始生产。" << endl;
	Prodect *A = factoryA->getProdect();
	Prodect *B = factoryB->getProdect();
	Prodect *C = factoryC->getProdect();
	int applePrice = A->getPrice();
	int bananaPrice = B->getPrice();
	int pearPrice = C->getPrice();
	int sum = A->getPrice() + B->getPrice() + C->getPrice();
	cout << "苹果价格:" << applePrice << "元。" << endl;
	cout << "香蕉价格:" << bananaPrice << "元。" << endl;
	cout << "梨子价格:" << pearPrice << "元。" << endl;
	cout << "累计消费:" << sum << "元。" << endl;
	delete A;
	delete B;
	delete C;
    delete factoryA;
    delete factoryB;
    delete factoryC;
	cout << "享用完毕。" << endl;
	return 0;
}

       程序结果如下。

        这样设计的好处就是如果多一个产品,那就只需要在产品类和工厂类中各扩展一个子类即可,不影响原有的程序。

四、总结

       我尽可能用较通俗的话语和直观的代码例程,来表述我对工厂模式的理解,或许有考虑不周到的地方,如果你有不同看法欢迎评论区交流!希望我举的例子能帮助你更好地理解工厂模式。

       如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

  • 10
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
好的,下面是将多个 C++ 文件封装成一个动态库的步骤: 1. 编写多个 C++ 文件,例如 `hello.cpp` 和 `world.cpp`: ```cpp // hello.cpp #include <iostream> void hello() { std::cout << "Hello, "; } // world.cpp #include <iostream> void world() { std::cout << "world!" << std::endl; } ``` 2. 使用 `-c` 选项分别将这些文件编译成目标文件,例如: ```bash g++ -c hello.cpp g++ -c world.cpp ``` 这里的 `-c` 选项表示只编译成目标文件,不链接生成可执行文件。 3. 将这些目标文件链接成一个动态库,使用下面的命令: ```bash g++ -shared -fPIC hello.o world.o -o libhelloworld.so ``` 这里的 `-shared` 选项表示编译成动态库,`-fPIC` 表示生成位置无关代码,`-o` 指定输出文件名。 4. 测试动态库,编写测试代码: ```cpp #include <dlfcn.h> int main() { void *handle = dlopen("./libhelloworld.so", RTLD_LAZY); if (!handle) { std::cerr << dlerror() << std::endl; return 1; } typedef void (*hello_t)(); hello_t hello = (hello_t) dlsym(handle, "hello"); if (!hello) { std::cerr << dlerror() << std::endl; return 1; } typedef void (*world_t)(); world_t world = (world_t) dlsym(handle, "world"); if (!world) { std::cerr << dlerror() << std::endl; return 1; } hello(); world(); dlclose(handle); return 0; } ``` 这里使用 `dlopen` 打开动态库,`dlsym` 获取导出函数地址,然后调用导出函数。 5. 编译测试代码,使用下面的命令: ```bash g++ test.cpp -ldl -o test ``` 这里的 `-ldl` 选项表示链接动态链接器。 6. 运行测试程序,使用下面的命令: ```bash ./test ``` 如果一切正常,就会输出 `Hello, world!`。 这样就成功将多个 C++ 文件封装成一个动态库,并且测试了动态库的导出函数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

翟天保Steven

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值