python--设计模式--18--行为型--访问者模式

发布时间:2026/5/20 3:45:12

python--设计模式--18--行为型--访问者模式 访问者模式Visitor Pattern访问者模式是一种将算法与对象结构分离的设计模式。它的核心思想是可以在不修改现有类的情况下为这些类添加新的操作。1 核心概念元素Element接受访问者的对象定义accept方法访问者Visitor定义对每个元素的访问操作每个具体访问者实现不同的操作2 缺点优点开闭原则在不修改元素类的情况下添加新操作单一职责将相关操作集中在一个访问者中累积状态访问者可以在遍历时积累信息灵活性不同的访问者可以执行不同的操作缺点元素类必须暴露足够的信息访问者可能需要访问元素的内部状态添加新元素困难每添加一个新元素所有访问者都需要修改可能破坏封装访问者可能需要访问元素的私有成员总结访问者模式的核心是将数据结构与操作分离特别适合以下场景对象结构稳定但经常需要添加新操作需要对对象结构中的元素执行多种不同且不相关的操作操作需要在不同元素类上执行不同的处理与其他模式的区别与迭代器模式迭代器遍历元素访问者对元素执行操作与策略模式策略封装算法访问者封装对对象结构的操作与组合模式组合模式构建对象树访问者遍历并操作树实际应用示例示例文档导出系统fromabcimportABC,abstractmethod# 元素接口classDocumentElement(ABC):文档元素抽象类abstractmethoddefaccept(self,visitor):接受访问者pass# 具体元素类classParagraph(DocumentElement):段落元素def__init__(self,text,alignmentleft):self.texttext self.alignmentalignment self.font_size12self.font_familyArialdefaccept(self,visitor):visitor.visit_paragraph(self)def__str__(self):returnf段落:{self.text[:20]}...classImage(DocumentElement):图片元素def__init__(self,path,width,height):self.pathpath self.widthwidth self.heightheight self.captiondefaccept(self,visitor):visitor.visit_image(self)def__str__(self):returnf图片:{self.path}({self.width}x{self.height})classTable(DocumentElement):表格元素def__init__(self,rows,cols,data):self.rowsrows self.colscols self.datadata self.borderTruedefaccept(self,visitor):visitor.visit_table(self)def__str__(self):returnf表格:{self.rows}x{self.cols}classDocument:文档类 - 对象结构def__init__(self,title):self.titletitle self.elements[]defadd_element(self,element):self.elements.append(element)defaccept(self,visitor):接受访问者遍历所有元素print(f\n处理文档:{self.title})forelementinself.elements:element.accept(visitor)# 访问者接口classDocumentVisitor(ABC):文档访问者抽象类abstractmethoddefvisit_paragraph(self,paragraph):passabstractmethoddefvisit_image(self,image):passabstractmethoddefvisit_table(self,table):pass# 具体访问者1HTML导出classHTMLExportVisitor(DocumentVisitor):HTML导出访问者def__init__(self):self.html_content[]defvisit_paragraph(self,paragraph):styleftext-align:{paragraph.alignment}; font-size:{paragraph.font_size}px;htmlfp style{style}{paragraph.text}/pself.html_content.append(html)print(f [HTML] 导出段落:{paragraph.text[:20]}...)defvisit_image(self,image):htmlfimg src{image.path} width{image.width} height{image.height}ifimage.caption:htmlf alt{image.caption}htmlself.html_content.append(html)print(f [HTML] 导出图片:{image.path})defvisit_table(self,table):html[table border1]# 添加表头html.append( theadtr)forjinrange(table.cols):html.append(f th列{j1}/th)html.append( /tr/thead)# 添加数据html.append( tbody)foriinrange(min(table.rows,len(table.data))):html.append( tr)forjinrange(table.cols):valuetable.data[i][j]ifilen(table.data)andjlen(table.data[i])elsehtml.append(f td{value}/td)html.append( /tr)html.append( /tbody)html.append(/table)self.html_content.extend(html)print(f [HTML] 导出表格:{table.rows}x{table.cols})defget_result(self):return\n.join(self.html_content)# 具体访问者2文本统计classStatisticsVisitor(DocumentVisitor):统计访问者def__init__(self):self.stats{paragraphs:0,images:0,tables:0,total_chars:0,total_image_size:0,total_cells:0}defvisit_paragraph(self,paragraph):self.stats[paragraphs]1self.stats[total_chars]len(paragraph.text)print(f [统计] 段落字数:{len(paragraph.text)})defvisit_image(self,image):self.stats[images]1self.stats[total_image_size]image.width*image.heightprint(f [统计] 图片尺寸:{image.width}x{image.height})defvisit_table(self,table):self.stats[tables]1cellstable.rows*table.cols self.stats[total_cells]cellsprint(f [统计] 表格单元格:{cells})defget_result(self):returnf 文档统计结果: - 段落数:{self.stats[paragraphs]}- 图片数:{self.stats[images]}- 表格数:{self.stats[tables]}- 总字符数:{self.stats[total_chars]}- 图片总面积:{self.stats[total_image_size]}像素 - 总单元格数:{self.stats[total_cells]}# 具体访问者3文本提取classTextExtractorVisitor(DocumentVisitor):文本提取访问者def__init__(self):self.text_parts[]defvisit_paragraph(self,paragraph):self.text_parts.append(paragraph.text)print(f [提取] 提取段落文本)defvisit_image(self,image):ifimage.caption:self.text_parts.append(f[图片:{image.caption}])else:self.text_parts.append([图片])print(f [提取] 添加图片标记)defvisit_table(self,table):self.text_parts.append([表格数据])# 提取表格数据foriinrange(min(table.rows,len(table.data))):row_text | .join(str(cell)forcellintable.data[i][:table.cols])self.text_parts.append(f{row_text})print(f [提取] 提取表格数据)defget_result(self):return\n.join(self.text_parts)defdocument_example():print( 文档访问者模式示例 \n)# 创建文档docDocument(项目报告)# 添加元素doc.add_element(Paragraph(这是一个关于访问者模式的示例文档。,left))doc.add_element(Paragraph(它展示了如何在不修改元素类的情况下添加新功能。,center))doc.add_element(Image(chart.png,800,600))doc.add_element(Table(3,3,[[产品,销量,收入],[A,100,¥1000],[B,200,¥2000]]))# 使用HTML导出访问者print(1. HTML导出操作:)html_visitorHTMLExportVisitor()doc.accept(html_visitor)print(\nHTML结果预览:)print(html_visitor.get_result()[:200]...)# 使用统计访问者print(\n2. 统计操作:)stats_visitorStatisticsVisitor()doc.accept(stats_visitor)print(stats_visitor.get_result())# 使用文本提取访问者print(3. 文本提取操作:)text_visitorTextExtractorVisitor()doc.accept(text_visitor)print(\n提取的文本:)print(text_visitor.get_result())if__name____main__:document_example()

相关新闻