一、工厂模式是什么?
工厂模式是一种创建型设计模式,它提供了一种将对象的实例化与使用代码分离的方式。这种模式通过定义一个公共接口来创建对象,而不是直接使用构造函数来创建对象。通过使用工厂模式,我们可以将对象的创建和使用代码解耦,使得代码更加灵活和可维护。
在python里可以搭配枚举类一块来实现。我们今天一起来结合langchain-chatchat的代码来学习它们
二、枚举类型
1. 代码示例
from enum import Enum
class SupportedVSType(Enum):
FAISS = 'faiss'
MILVUS = 'milvus'
DEFAULT = 'default'
ZILLIZ = 'zilliz'
PG = 'pg'
ES = 'es'
CHROMADB = 'chromadb'
2. 解说
枚举类是一种特殊的类,用于定义一个固定的、有限的值集合。在Python中,可以通过定义一个类来实现枚举。枚举类的每个值都是类的一个实例,这些实例可以直接通过类名来访问。
在给定的例子中,SupportedVSType是一个枚举类,它定义了一组支持的垂直搜索类型。每个垂直搜索类型都是SupportedVSType类的一个实例。例如,FAISS、MILVUS、DEFAULT等都是SupportedVSType类的实例。
枚举类的优点是可以确保值的唯一性和类型安全性。例如,不可能创建SupportedVSType类的另一个实例,除非新的值添加到枚举类中。
通过定义枚举类,可以很方便地在代码中使用这些固定的值。例如,可以直接使用SupportedVSType.FAISS来表示FAISS类型的垂直搜索。
3. 特别注意的一点
还是要强调下,枚举类每个值都是这个枚举类的一个实例。很多人会把它误以为是类的一个属性,导致无法理解枚举类的用法。
也就是
isinstance(SupportedVSType.FAISS, SupportedVSType) 结果是true
二、工厂模式
1. 代码示例
以下代码是从langchain-chatchat里摘录并精简后的
class KBServiceFactory:
@staticmethod
def get_service(kb_name: str,
vector_store_type: Union[str, SupportedVSType],
embed_model: str = EMBEDDING_MODEL,
) -> KBService:
if isinstance(vector_store_type, str):
vector_store_type = getattr(SupportedVSType, vector_store_type.upper())
if SupportedVSType.FAISS == vector_store_type:
from server.knowledge_base.kb_service.faiss_kb_service import FaissKBService
return FaissKBService(kb_name, embed_model=embed_model)
elif SupportedVSType.PG == vector_store_type:
from server.knowledge_base.kb_service.pg_kb_service import PGKBService
return PGKBService(kb_name, embed_model=embed_model)
2. 解读
在上述代码中,KBServiceFactory是一个工厂类,它提供了创建KBService对象的方法。根据不同的vector_store_type创建对应的KBService对象。首先将vector_store_type转换为SupportedVSType类型,然后根据不同的SupportedVSType值选择对应的实现类来创建KBService对象。
要说明的一点 : vector_store_type: Union[str, SupportedVSType]
这一段是表示一个函数参数的类型注解。它表示这个参数可以是一个字符串类型,也可以是一个SupportedVSType类的对象。
3. 使用工厂模式有什么好处
-
封装对象的创建过程:工厂模式将对象的创建逻辑封装在工厂类中,客户端无需关心对象的具体创建细节,只需要调用工厂方法即可获取所需的对象实例。
-
降低耦合性:工厂模式将客户端代码与具体的对象实现解耦,客户端只需要依赖工厂类而不是具体的对象类。这样,当需要替换或增加新的对象时,只需要修改工厂类而无需修改客户端代码,从而提高了系统的灵活性和可维护性。
-
提供统一的接口:工厂模式通过提供一个统一的接口来创建对象,使得客户端可以通过相同的方式创建不同类型的对象。这样,客户端无需知道具体的对象类,只需要知道工厂方法的名称和参数,就能够创建所需的对象。
4)可以隐藏对象创建的细节:工厂模式可以将对象的创建逻辑封装在工厂类中,客户端无需了解对象的创建过程,只需要调用工厂方法来获取对象实例。这样可以隐藏对象的创建细节,保护对象的实现细节和内部状态,提高了系统的安全性和稳定性。
总结
工厂模式可以提供一个统一的接口来封装对象的创建过程,降低客户端代码与具体对象之间的耦合性,并隐藏对象的创建细节,提高了系统的灵活性、可维护性、安全性和稳定性。