【设计模式】简单工厂、工厂方法和抽象工厂

目录

  • [Simple Factory简单工厂](#Simple Factory简单工厂)
  • [Factory Method工厂方法](#Factory Method工厂方法)
  • [Abstract Factory抽象工厂](#Abstract Factory抽象工厂)
  • 总结

橙色

Simple Factory简单工厂

通过传入一个事先设计好的枚举类型,然后返回一个对应的对象,既解耦了对象的创建,还不用再记忆那么多的类名

cpp 复制代码
#include <iostream>
#include <string>
#include <memory>
using namespace std;
// 产品类型
class Product
{
public:
	Product(string name) :_name(name) {}
	// 模拟产品对象的一个抽象方法
	virtual void show() = 0;
protected:
	string _name;
};

// 产品实体类型定义
class ProductA : public Product
{
public:
	ProductA(string name) :Product(name){}
	void show() { cout << "获取了一个ProductA对象:" << _name << endl; }
};
// 产品实体类型定义
class ProductB : public Product
{
public:
	ProductB(string name) :Product(name) {}
	void show() { cout << "获取了一个ProductB对象:" << _name << endl;
	}
};

// 产类枚举类型定义
enum ProductType
{
	XIAOMI,
	HUAWEI,
};
// 简单工厂类
class SimpleFactory
{
public:
	// 通过传入的枚举类型,创建相应的对象,返回所有对象的基类指针
	Product* createProduct(ProductType type)
	{
		switch (type)
		{
		case XIAOMI:
			return new ProductA("小米手机");
		case HUAWEI:
			return new ProductB("华为手机");
        default:
            cerr << "传入工厂的参数不正确:" << type << endl;
            break;
        }
        return nullptr;
    }
};

int main()
{
	// 创建简单工厂实例
	SimpleFactory sf;

	// 使用智能指针自动释放堆内存
	unique_ptr<Product> p1(sf.createProduct(XIAOMI));
	unique_ptr<Product> p2(sf.createProduct(HUAWEI));

	p1->show();
	p2->show();

	return 0;
}

SimpleFactory简单工厂解决了一些问题,但是它本身也有很明显的问题,就是把所有对象的创建都封装在了一个SimpleFactory类的createProduct函数中,根据传入的参数,选择产生不同的对象,很明显,createProduct这个函数做不到"开-闭"原则,即对原有代码修改关闭,对功能扩展开放,这个函数随着新对象的添加,或者原有对象的删除,都会导致该函数的代码修改,而且有可能影响原来的功能,所以这样的设计不能算完美。

那么接下来看看工厂方法(Factory Method)模式是否能够解决上面简单工厂的问题。

Factory Method工厂方法

cpp 复制代码
#include <iostream>
#include <string>
#include <memory>
using namespace std;

// 产品类型
class Product
{
public:
	Product(string name) :_name(name) {}
	// 模拟产品对象的一个抽象方法
	virtual void show() = 0;
protected:
	string _name;
};
// 产品实体类型定义
class ProductA : public Product
{
public:
	ProductA(string name) :Product(name){}
	void show() { cout << "获取了一个使用老外高通芯片的手机:" << _name << endl; }
};
// 产品实体类型定义
class ProductB : public Product
{
public:
	ProductB(string name) :Product(name) {}
	void show() { cout << "获取了一个使用自研麒麟芯片的手机:" << _name << endl;
	}
};

// 工厂基类
class Factory
{
public:
	virtual Product* createProduct() = 0;
};

// 生产小米手机的工厂
class XiaomiFactory : public Factory
{
public:
	Product* createProduct()
	{
		// 小米工厂肯定生产小米手机
		return new ProductA("小米手机");
	}
};
// 生产华为手机的工厂
class HuaweiFactory : public Factory
{
public:
	Product* createProduct()
	{
		// 华为工厂肯定生产华为手机
		return new ProductB("华为手机");
	}
};

int main()
{
	// 使用智能指针自动释放堆内存
	// 创建具体的工厂
	unique_ptr<Factory> f1(new XiaomiFactory);
	unique_ptr<Factory> f2(new HuaweiFactory);

	// 通过工厂方法创建产品
	unique_ptr<Product> p1(f1->createProduct());
	unique_ptr<Product> p2(f2->createProduct());

	p1->show();
	p2->show();

	return 0;
}

仔细理解上面的工厂方法模式,会发现一个问题,就是每一个实例工厂负责生产一个实例产品,也就是一个产品对应一个工厂,一个工厂对应一个产品,那么小米不仅仅生产手机,还生产耳机,智能手环,智能插座等等相关的小米产品簇,不可能给这每一个产品都创建一个工厂类,那样的话代码中的类就太多了,不好维护,而且也不符合实际情况。

实际上小米或者华为的工厂里面,有相关联的产品簇都是在一个工厂完成创建的;BMW或者Audi汽车制造工厂除了生产汽车,生产线上也有可能生产轮胎,或者其它的汽车附属产品。

所以对于包含产品簇这么一类实体关系的设计,就需要使用Abstract Factory抽象工厂了,你也可以把上面的工厂方法看作只生产一种产品的抽象工厂,本质是相同的。

Abstract Factory抽象工厂

cpp 复制代码
#include <iostream>
#include <string>
#include <memory>
using namespace std;

// 产品簇手机类型
class ProductA
{
public:
	ProductA(string name) :_name(name) {}
	// 模拟产品对象的一个抽象方法
	virtual void show() = 0;
protected:
	string _name;
};
// 产品实体类型定义
class XiaomiPhone : public ProductA
{
public:
	XiaomiPhone(string name) :ProductA(name){}
	void show() { cout << "获取了一个小米手机:" << _name << endl; }
};
// 产品实体类型定义
class HuaweiPhone : public ProductA
{
public:
	HuaweiPhone(string name) :ProductA(name) {}
	void show() { cout << "获取了一个华为手机:" << _name << endl;
	}
};

// 产品簇智能手环类型
class ProductB
{
public:
	ProductB(string name) :_name(name) {}
	// 模拟产品对象的一个抽象方法
	virtual void show() = 0;
protected:
	string _name;
};
// 产品实体类型定义
class XiaomiCircle : public ProductB
{
public:
	XiaomiCircle(string name) :ProductB(name) {}
	void show() { cout << "获取了一个小米智能手环设备:" << _name << endl; }
};
// 产品实体类型定义
class HuaweiCircle : public ProductB
{
public:
	HuaweiCircle(string name) :ProductB(name) {}
	void show() {
		cout << "获取了一个华为智能手环设备:" << _name << endl;
	}
};

// 工厂方法=》抽象工厂(对有一组关联关系的产品簇提供产品对象的统一创建)
class AbstractFactory
{
public:
	// 工厂里面创建手机的纯虚函数接口
	virtual ProductA* createPhone() = 0;
	// 工厂里面创建智能手环的纯虚函数接口
	virtual ProductB* createSmartCircle() = 0;
};

// 生产小米产品簇的工厂
class XiaomiFactory : public AbstractFactory
{
public:
	ProductA* createPhone()
	{
		// 小米工厂肯定生产小米手机
		return new XiaomiPhone("小米x9");
	}
	ProductB* createSmartCircle()
	{
		// 小米工厂肯定生产小米智能手环
		return new XiaomiCircle("小米智能手环2代时尚版");
	}
};
// 生产华为产品簇的工厂
class HuaweiFactory : public AbstractFactory
{
public:
	ProductA* createPhone()
	{
		// 华为工厂肯定生产华为手机
		return new HuaweiPhone("华为荣耀7x");
	}
	ProductB* createSmartCircle()
	{
		// 华为工厂肯定生产华为智能手环
		return new HuaweiCircle("华为智能手环B3青春版");
	}
};

int main()
{
	// 使用智能指针自动释放堆内存
	// 创建具体的工厂
	unique_ptr<AbstractFactory> f1(new XiaomiFactory);
	unique_ptr<AbstractFactory> f2(new HuaweiFactory);

	// 通过工厂方法创建手机产品
	unique_ptr<ProductA> p1(f1->createPhone());
	unique_ptr<ProductA> p2(f2->createPhone());
	p1->show();
	p2->show();

	// 通过工厂方法创建智能手环产品
	unique_ptr<ProductB> p3(f1->createSmartCircle());
	unique_ptr<ProductB> p4(f2->createSmartCircle());
	p3->show();
	p4->show();

	return 0;
}

总结

工厂模式:主要是封装了对象的创建

简单工厂:

把对象的创建封装在一个接口函数里面,通过传入不同的标识,返回创建的对象,客户不用自己负责new对象,不用了解对象创建的详细过程。

提供创建对象实例的接口函数不闭合,不能对修改关闭

工厂方法:

Factory基类,提供了一个纯虚函数(创建产品),定义派生类(具体产品的工厂)负责创建对应的产品,可以做到不同的产品,在不同的工厂里面创建,能够对现有工厂,以及产品的修改关闭

实际上,很多产品是有关联关系的,属于一个产品簇,不应该放在不同的工厂里面去创建,这样一是不符合实际的产品对象创建逻辑,二是工厂类太多了,不好维护

抽象工厂:

把有关联关系的,属于一个产品簇的所有产品创建的接口函数,放在一个抽象工厂里面,派生类(具体产品的工厂)应该负责创建该产品簇里面所有的产品

相关推荐
晨米酱10 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机15 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机16 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机16 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机16 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤16 小时前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机1 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机2 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴2 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
李广坤2 天前
工厂模式
设计模式