
一、开篇把创建对象交给专门的人在代码中直接写obj SomeClass()就把使用者和具体类绑死了。如果以后要换一种实现就要改所有SomeClass()的地方。工厂模式解决的就是这个问题——把对象的创建集中管理。⌨️ 先看问题# ❌ 硬编码——紧耦合defprocess_payment(amount,method):ifmethodwechat:processorWeChatPay()# 直接创建elifmethodalipay:processorAlipay()elifmethodcredit_card:processorCreditCard()# 每次新增支付方式——修改这个函数processor.pay(amount)# ✅ 工厂模式——解耦defprocess_payment(amount,method):processorPaymentFactory.create(method)# 工厂创建processor.pay(amount)# 新增支付方式——只需要改工厂二、简单工厂模式2.1 基本实现fromabcimportABC,abstractmethod# 产品接口 classPaymentProcessor(ABC):abstractmethoddefpay(self,amount):pass# 具体产品 classWeChatPay(PaymentProcessor):defpay(self,amount):print(f微信支付 ¥{amount})classAlipay(PaymentProcessor):defpay(self,amount):print(f支付宝支付 ¥{amount})classCreditCardPay(PaymentProcessor):defpay(self,amount):print(f信用卡支付 ¥{amount})# 简单工厂 classPaymentFactory:支付处理器工厂_processors{wechat:WeChatPay,alipay:Alipay,credit_card:CreditCardPay,}classmethoddefcreate(cls,method):根据方法名创建对应的处理器processor_classcls._processors.get(method)ifprocessor_classisNone:raiseValueError(f不支持的支付方式:{method})returnprocessor_class()classmethoddefregister(cls,method,processor_class):注册新的支付方式扩展点cls._processors[method]processor_class# 使用processorPaymentFactory.create(wechat)processor.pay(100)# 扩展——新增支付方式不需要修改现有代码classApplePay(PaymentProcessor):defpay(self,amount):print(fApple Pay支付 ¥{amount})PaymentFactory.register(apple,ApplePay)PaymentFactory.create(apple).pay(200)2.2 带配置的工厂# 工厂根据配置创建合适的对象classDatabaseConnection(ABC):abstractmethoddefconnect(self):passclassMySQLConnection(DatabaseConnection):def__init__(self,host,port,database):self.hosthost self.portport self.databasedatabasedefconnect(self):returnfMySQL:{self.host}:{self.port}/{self.database}classPostgreSQLConnection(DatabaseConnection):def__init__(self,host,port,database):self.hosthost self.portport self.databasedatabasedefconnect(self):returnfPostgreSQL:{self.host}:{self.port}/{self.database}classSQLiteConnection(DatabaseConnection):def__init__(self,filepath):self.filepathfilepathdefconnect(self):returnfSQLite:{self.filepath}classConnectionFactory:数据库连接工厂——根据URL自动选择驱动staticmethoddefcreate(connection_url):mysql://host:port/db → MySQL连接ifconnection_url.startswith(mysql://):# 解析URL简化版partsconnection_url.replace(mysql://,).split(/)host_portparts[0].split(:)hosthost_port[0]portint(host_port[1])iflen(host_port)1else3306databaseparts[1]iflen(parts)1elsetestreturnMySQLConnection(host,port,database)elifconnection_url.startswith(postgresql://):partsconnection_url.replace(postgresql://,).split(/)host_portparts[0].split(:)hosthost_port[0]portint(host_port[1])iflen(host_port)1else5432databaseparts[1]iflen(parts)1elsetestreturnPostgreSQLConnection(host,port,database)elifconnection_url.startswith(sqlite://):filepathconnection_url.replace(sqlite://,)returnSQLiteConnection(filepath)else:raiseValueError(f不支持的数据库:{connection_url})# 使用——一行决定用什么数据库# conn ConnectionFactory.create(mysql://localhost:3306/mydb)# conn ConnectionFactory.create(postgresql://localhost/mydb)# conn ConnectionFactory.create(sqlite://app.db)三、工厂方法模式3.1 让子类决定创建什么# 工厂方法模式定义一个创建对象的接口# 让子类决定实例化哪个类fromabcimportABC,abstractmethod# 产品 classDocument(ABC):abstractmethoddefopen(self):passabstractmethoddefsave(self):passclassPDFDocument(Document):defopen(self):return打开PDF文档defsave(self):return保存为PDF格式classWordDocument(Document):defopen(self):return打开Word文档defsave(self):return保存为Word格式classMarkdownDocument(Document):defopen(self):return打开Markdown文档defsave(self):return保存为Markdown格式# 创建者抽象工厂 classDocumentCreator(ABC):文档创建者——工厂方法模式的核心abstractmethoddefcreate_document(self):工厂方法——子类决定创建什么文档passdefnew_document(self):模板方法——使用工厂方法docself.create_document()print(f创建文档:{doc.open()})returndocclassPDFCreator(DocumentCreator):defcreate_document(self):returnPDFDocument()classWordCreator(DocumentCreator):defcreate_document(self):returnWordDocument()classMarkdownCreator(DocumentCreator):defcreate_document(self):returnMarkdownDocument()# 使用——每个创建者生产一种文档pdf_creatorPDFCreator()docpdf_creator.new_document()print(doc.save())3.2 实战数据导出器fromabcimportABC,abstractmethodimportjsonimportcsv# 产品 classDataExporter(ABC):abstractmethoddefexport(self,data,filepath):passclassJsonExporter(DataExporter):defexport(self,data,filepath):withopen(filepath,w,encodingutf-8)asf:json.dump(data,f,ensure_asciiFalse,indent2)returnf已导出JSON:{filepath}classCsvExporter(DataExporter):defexport(self,data,filepath):withopen(filepath,w,newline,encodingutf-8-sig)asf:writercsv.DictWriter(f,fieldnamesdata[0].keys())writer.writeheader()writer.writerows(data)returnf已导出CSV:{filepath}# 创建者 classExportService(ABC):导出服务——把创建逻辑作为工厂方法abstractmethoddefcreate_exporter(self):passdefexport_data(self,data,filepath):exporterself.create_exporter()returnexporter.export(data,filepath)classJsonExportService(ExportService):defcreate_exporter(self):returnJsonExporter()classCsvExportService(ExportService):defcreate_exporter(self):returnCsvExporter()# 使用data[{name:张三,age:25},{name:李四,age:30}]serviceJsonExportService()print(service.export_data(data,output.json))四、Python中的工厂简化# Python的灵活语法可以大大简化工厂模式# 简化一用字典代替if-elif链factory{json:JsonExporter,csv:CsvExporter,}exporterfactory.get(json,JsonExporter)()# 简化二用函数代替工厂类defcreate_exporter(format_type):工厂函数——Python中一个函数就够了exporters{json:JsonExporter,csv:CsvExporter}exporter_classexporters.get(format_type)ifexporter_classisNone:raiseValueError(f不支持的格式:{format_type})returnexporter_class()# 简化三用__init_subclass__自动注册classAutoRegisteredExporter(DataExporter):_registry{}def__init_subclass__(cls,format_nameNone,**kwargs):super().__init_subclass__(**kwargs)ifformat_name:cls._registry[format_name]clsclassmethoddefcreate(cls,format_name):returncls._registry[format_name]()classJsonExporterV2(AutoRegisteredExporter,format_namejson):passclassCsvExporterV2(AutoRegisteredExporter,format_namecsv):pass# 新增格式自动注册classXmlExporter(AutoRegisteredExporter,format_namexml):passprint(AutoRegisteredExporter._registry)# {json: ..., csv: ..., xml: ...}五、总结工厂模式是创建型设计模式中最常用的——它把创建什么对象的决定集中管理让系统更容易扩展。核心要点模式特点适用场景简单工厂一个工厂类创建所有产品产品种类少、固定工厂方法每个产品有对应的工厂产品可能扩展Python风格用字典函数大多数日常场景✅当你发现代码中有if type A: ... elif type B: ...这种创建逻辑时——考虑提取到工厂中。