完整教程:基于类的四种设计模式

news/2025/11/1 15:22:56/文章来源:https://www.cnblogs.com/slgkaifa/p/19183406

完整教程:基于类的四种设计模式

1. 工厂方法模式 (Factory Method)

问题

当系统需要创建对象,但具体类型在编译时无法确定,或者创建逻辑复杂需要封装时,直接使用new关键字会导致代码耦合度高、难以扩展。

解决方案

定义一个创建对象的接口,但让子类决定实例化哪个类。工厂方法让类的实例化推迟到子类。

组件框图

┌─────────────────┐         ┌──────────────────┐
│    Creator      │         │    Product       │
├─────────────────┤         ├──────────────────┤
│+factoryMethod() │───────>│                  │
└─────────────────┘         └──────────────────┘
         ▲                            ▲
         │                            │
┌─────────────────┐         ┌──────────────────┐
│ ConcreteCreator │         │ ConcreteProduct  │
├─────────────────┤         ├──────────────────┤
│+factoryMethod() │         │                  │
└─────────────────┘         └──────────────────┘

效果

优点:

  • 符合开闭原则,易于扩展新产品

  • 客户端与具体产品类解耦

  • 将创建逻辑集中管理

缺点:

  • 每增加一个产品就需要增加一个具体工厂类

  • 增加了系统的复杂度

代码示例(Python重点展示)

from abc import ABC, abstractmethod
class Document(ABC):@abstractmethoddef open(self):pass@abstractmethoddef save(self):pass
class WordDocument(Document):def open(self):print("打开Word文档")def save(self):print("保存Word文档")
class PDFDocument(Document):def open(self):print("打开PDF文档")def save(self):print("保存PDF文档")
class Application(ABC):def __init__(self):self.documents = []@abstractmethoddef create_document(self) -> Document:passdef new_document(self):doc = self.create_document()self.documents.append(doc)doc.open()return doc
class WordApplication(Application):def create_document(self) -> Document:return WordDocument()
class PDFApplication(Application):def create_document(self) -> Document:return PDFDocument()
# 使用
app = WordApplication()
doc = app.new_document()  # 输出: 打开Word文档

2. 基于类的适配器模式 (Class Adapter)

问题

现有类的接口与客户端期望的接口不兼容,但需要让它们能够协同工作,且不希望修改现有代码。

解决方案

通过多重继承(或实现接口+继承)创建一个适配器类,它同时继承目标接口和被适配者,在适配器类中实现接口转换。

组件框图

┌─────────────────┐         ┌──────────────────┐
│    Client       │         │    Target        │
├─────────────────┤         ├──────────────────┤
│                 │───────>│+request()        │
└─────────────────┘         └──────────────────┘▲│┌──────────────────┐│    Adapter       │├──────────────────┤│+request()        │└──────────────────┘▲│┌──────────────────┐│   Adaptee        │├──────────────────┤│+specificRequest()│└──────────────────┘

效果

优点:

  • 可以让任何两个没有关联的类一起运行

  • 提高了类的复用性

  • 符合开闭原则

缺点:

  • 过多使用适配器会让系统变得混乱

  • 由于使用继承,限制了适配器的灵活性

代码示例(C++重点展示)

#include 
#include 
// 目标接口 - 欧洲插座
class EuropeanSocket {
public:virtual ~EuropeanSocket() = default;virtual void plugIn() = 0;virtual int getVoltage() = 0;
};
// 被适配者 - 美国插座
class AmericanSocket {
public:void connect() {std::cout << "美国插座连接" << std::endl;}int getUSVoltage() {return 110;  // 110V}
};
// 适配器 - 旅行转换器
class SocketAdapter : public EuropeanSocket, private AmericanSocket {
public:void plugIn() override {std::cout << "使用适配器连接: ";connect();  // 调用被适配者的方法std::cout << "将电压从" << getUSVoltage() << "V转换到" << getVoltage() << "V" << std::endl;}int getVoltage() override {return 220;  // 转换为欧洲电压}
};
// 欧洲电器
class EuropeanDevice {
public:void use(EuropeanSocket* socket) {socket->plugIn();std::cout << "设备在 " << socket->getVoltage() << "V 电压下工作" << std::endl;}
};
// 使用
int main() {EuropeanDevice device;SocketAdapter adapter;device.use(&adapter);return 0;
}

3. 解释器模式 (Interpreter)

问题

需要解释执行特定语言或文法规则,且文法规则可以表示为层次结构。例如:正则表达式、数学表达式、SQL查询等。

解决方案

定义文法的类层次结构,每个规则对应一个类,通过组合模式构建抽象语法树,实现解释操作。

组件框图

┌─────────────────┐         ┌──────────────────┐
│   Client        │         │  AbstractExpression
├─────────────────┤         ├──────────────────┤
│                 │───────>│+interpret(Context)│
└─────────────────┘         └──────────────────┘△┌────────────────┼────────────────┐┌────────────┴────────────┐    ┌──────────────┴────────────┐│     TerminalExpression  │    │  NonterminalExpression    │├─────────────────────────┤    ├───────────────────────────┤│+interpret(Context)      │    │+interpret(Context)        │└─────────────────────────┘    │-expression                │└───────────────────────────┘

效果

优点:

  • 易于改变和扩展文法

  • 实现文法很容易,类层次结构清晰

  • 易于实现简单文法

缺点:

  • 复杂的文法难以维护

  • 执行效率较低

  • 类数量会随着规则增加而增加

代码示例(C#重点展示)

using System;
using System.Collections.Generic;
// 上下文 - 存储变量值
public class Context
{private Dictionary variables = new Dictionary();public void SetVariable(string name, bool value){variables[name] = value;}public bool GetVariable(string name){return variables.ContainsKey(name) ? variables[name] : false;}
}
// 抽象表达式
public interface IExpression
{bool Interpret(Context context);
}
// 终结符表达式 - 变量
public class VariableExpression : IExpression
{private string name;public VariableExpression(string name){this.name = name;}public bool Interpret(Context context){return context.GetVariable(name);}
}
// 终结符表达式 - 常量
public class ConstantExpression : IExpression
{private bool value;public ConstantExpression(bool value){this.value = value;}public bool Interpret(Context context){return value;}
}
// 非终结符表达式 - 与操作
public class AndExpression : IExpression
{private IExpression left;private IExpression right;public AndExpression(IExpression left, IExpression right){this.left = left;this.right = right;}public bool Interpret(Context context){return left.Interpret(context) && right.Interpret(context);}
}
// 非终结符表达式 - 或操作
public class OrExpression : IExpression
{private IExpression left;private IExpression right;public OrExpression(IExpression left, IExpression right){this.left = left;this.right = right;}public bool Interpret(Context context){return left.Interpret(context) || right.Interpret(context);}
}
// 非终结符表达式 - 非操作
public class NotExpression : IExpression
{private IExpression expression;public NotExpression(IExpression expression){this.expression = expression;}public bool Interpret(Context context){return !expression.Interpret(context);}
}
// 使用
class Program
{static void Main(){// 构建上下文:A=true, B=false, C=trueContext context = new Context();context.SetVariable("A", true);context.SetVariable("B", false);context.SetVariable("C", true);// 构建表达式: (A AND B) OR (NOT C)IExpression expression = new OrExpression(new AndExpression(new VariableExpression("A"),new VariableExpression("B")),new NotExpression(new VariableExpression("C")));bool result = expression.Interpret(context);Console.WriteLine($"表达式 (A AND B) OR (NOT C) 的结果: {result}");// 计算: (true AND false) OR (NOT true) = false OR false = false// 另一个表达式: A OR (B AND C)IExpression expression2 = new OrExpression(new VariableExpression("A"),new AndExpression(new VariableExpression("B"),new VariableExpression("C")));bool result2 = expression2.Interpret(context);Console.WriteLine($"表达式 A OR (B AND C) 的结果: {result2}");// 计算: true OR (false AND true) = true OR false = true}
}

4. 模板方法模式 (Template Method)

问题

多个类有相同的工作步骤,但某些步骤的具体实现不同。需要在保持算法结构不变的前提下,允许子类重新定义某些步骤。

解决方案

在抽象类中定义算法的骨架,将一些步骤的实现推迟到子类中。模板方法使得子类可以不改变算法结构的情况下重新定义算法的某些步骤。

组件框图

┌─────────────────┐
│ AbstractClass   │
├─────────────────┤
│+templateMethod()│
│+step1()         │
│+step2()         │
│#primitiveOp1()  │
│#primitiveOp2()  │
│#hook()          │
└─────────────────┘△│
┌─────────────────┐
│ ConcreteClass   │
├─────────────────┤
│#primitiveOp1()  │
│#primitiveOp2()  │
│#hook()          │
└─────────────────┘

效果

优点:

  • 代码复用,将不变行为移到超类

  • 符合开闭原则,易于扩展

  • 便于维护,算法结构集中管理

缺点:

  • 每个不同的实现都需要一个子类

  • 超类中的抽象方法必须由子类实现

  • 可能违反里氏替换原则

详细代码示例(Python)

from abc import ABC, abstractmethod
from datetime import datetime
class ReportGenerator(ABC):"""报表生成器模板类"""def generate_report(self):"""模板方法 - 定义报表生成流程"""self.collect_data()self.process_data()self.format_report()if self.needs_export():self.export_report()self.cleanup()def collect_data(self):"""具体方法 - 收集数据(所有报表通用)"""print(f"[{datetime.now()}] 开始收集数据...")# 模拟数据收集self.data = ["数据1", "数据2", "数据3"]print("数据收集完成")@abstractmethoddef process_data(self):"""抽象方法 - 处理数据(子类必须实现)"""pass@abstractmethoddef format_report(self):"""抽象方法 - 格式化报表(子类必须实现)"""passdef export_report(self):"""钩子方法 - 导出报表(子类可选重写)"""print("默认导出为PDF格式")def needs_export(self):"""钩子方法 - 是否需要导出(子类可选重写)"""return Truedef cleanup(self):"""具体方法 - 清理资源(所有报表通用)"""print("清理临时数据和资源...")
class SalesReportGenerator(ReportGenerator):"""销售报表生成器"""def process_data(self):"""实现销售数据处理的特定逻辑"""print("处理销售数据: 计算销售额、增长率等指标")self.processed_data = [f"销售指标: {item}" for item in self.data]def format_report(self):"""实现销售报表的特定格式"""print("格式化销售报表: 使用图表展示销售趋势")print("生成的报表内容:", self.processed_data)def export_report(self):"""重写导出方法 - 销售报表需要多种格式"""print("导出销售报表: PDF, Excel, 和HTML格式")
class FinancialReportGenerator(ReportGenerator):"""财务报表生成器"""def process_data(self):"""实现财务数据处理的特定逻辑"""print("处理财务数据: 计算利润、资产负债表等项目")self.processed_data = [f"财务项目: {item}" for item in self.data]def format_report(self):"""实现财务报表的特定格式"""print("格式化财务报表: 使用表格展示财务数据")print("生成的报表内容:", self.processed_data)def needs_export(self):"""重写钩子方法 - 财务报表不需要自动导出"""return Falsedef audit_trail(self):"""财务报表特有的审计追踪方法"""print("生成审计追踪记录")
class InventoryReportGenerator(ReportGenerator):"""库存报表生成器"""def process_data(self):"""实现库存数据处理的特定逻辑"""print("处理库存数据: 计算库存周转率、安全库存等")self.processed_data = [f"库存指标: {item}" for item in self.data]def format_report(self):"""实现库存报表的特定格式"""print("格式化库存报表: 使用条形图展示库存水平")print("生成的报表内容:", self.processed_data)def export_report(self):"""重写导出方法 - 库存报表需要实时同步"""print("导出库存报表并同步到ERP系统")
# 客户端代码
def main():print("=== 销售报表生成 ===")sales_report = SalesReportGenerator()sales_report.generate_report()print("\n=== 财务报表生成 ===")financial_report = FinancialReportGenerator()financial_report.generate_report()print("\n=== 库存报表生成 ===")inventory_report = InventoryReportGenerator()inventory_report.generate_report()
if __name__ == "__main__":main()

模式对比总结

模式主要目的适用场景关键特性
工厂方法对象创建解耦创建逻辑复杂或运行时确定类型子类决定创建对象
适配器模式接口转换集成不兼容的接口继承+接口实现
解释器模式语言解释特定领域语言处理文法类层次结构
模板方法算法骨架固定多个类有相同流程但不同实现抽象类定义模板

这些模式都体现了面向对象设计的重要原则:开闭原则、依赖倒置原则和里氏替换原则,在实际开发中可以根据具体需求灵活选用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/952852.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Go基础:正则表达式 regexp 库详解 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

JBoltAI 智能企业内训平台深度解析

企业内训智能化转型新标杆:JBoltAI 智能企业内训平台 在数字化转型浪潮下,企业培训模式正经历着从传统线下授课到全流程智能化的颠覆性变革。JBoltAI 智能企业内训平台作为企业培训领域的创新解决方案,凭借其 AI 驱…

2025 年 11 月云南财务服务,云南财税咨询,昆明代理记账公司最新推荐,技术实力与市场口碑深度解析!

2025 年 11 月,省税务师协会联合省数字财税发展研究院,针对全省 92 家开展云南财务服务、云南财税咨询、昆明代理记账业务的机构,开展以 “技术硬实力 + 市场好口碑” 为核心的专项测评。本次测评采用 “量化考核 +…

第四十五章 ESP32S3 Flash 模拟 U 盘实验 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

JBoltAI框架揭秘:如何为Java应用注入“企业级AI知识库”能力

JBoltAI框架揭秘:如何为Java应用注入“企业级AI知识库”能力在企业级AI应用中,RAG(检索增强生成)是实现智能问答、决策辅助等场景的核心技术。而其根基,在于一个高效、可控的AI知识库。今天,我们将深入介绍JBolt…

2025 年 11 月云南财税服务,昆明财税代理,云南代理记账公司最新推荐,实力品牌深度解析采购无忧之选!

2025 年 11 月,省注册会计师协会联合省中小企业财税服务联盟,针对全省 87 家开展云南财税服务、昆明财税代理、云南代理记账业务的机构,开展 “实力品牌专项测评”。本次测评采用 “三维度权重评估法”:品牌资质维…

电脑恢复技巧:适用于 Windows 的 9 款最佳分区恢复软件

磁盘分区对于妥善存储数据、方便快捷地从硬盘访问数据至关重要。然而,如果分区损坏,其中存储的所有数据将突然无法访问。磁盘分区损坏的原因有很多,其中最常见的包括病毒攻击、突然断电、物理损坏或坏扇区的产生。 …

2025 年 11 月云南环保咨询,云南环评手续咨询,云南环评批复咨询最新推荐:聚焦资质、案例、售后的五家机构深度解读!

为解决云南企业在环评服务选型中 “资质真伪难辨、案例适配性不明、售后保障缺失” 的核心痛点,云南省环境保护产业协会联合省环境工程评估中心开展 2025 年度专项测评,覆盖全省 268 家咨询机构,最终筛选出 5 家在资…

20251031周五日记

20251031周五日记今日: 1.起的贼早,去实验室看会儿文章去和祥吃必胜客炉石联动。被上了一课,以后要更明确地懂别人的隐藏动作意思呀。陪他买个蛋糕回去上课了。 2.回去先把东西放回宿舍,把杜的信寄走。去听汇报和课…

完整教程:毕设项目基于Django的医药管理系统\251006(白嫖源码+演示录像)可做计算机毕设JAVA、PHP、爬虫、APP、小程序、C#、C++、python、数据可视化、文案

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

CSP-J 2025 题解

第一题:拼数 (number) 思路分析 题目要求使用一个字符串中包含的数字字符拼成一个最大的正整数。 要组成最大的数,我们的策略应该是把越大的数字放在越高的位(即越靠前的位置)。例如,用数字 \(9, 2, 1, 0, 0\) 能…

人工智能之编程基础 Python 入门:第五章 基本数据类型(一)

人工智能之编程基础 Python 入门:第五章 基本数据类型(一)人工智能之编程基础 Python 入门 第五章 基础数据类型(一)@目录人工智能之编程基础 Python 入门前言Number(数字)1. 整数 (int)特点:示例:2. 浮点数 …

150行的推箱子游戏

150行的推箱子游戏#include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <ncurses.h> #include <algorithm> t…

嵌入式制作笔记(1)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

tmp2

3、复杂模型机累加指令 ;/*** Start Of Main Memory Data ****/ $P 00 20 ;START: IN R0,00H 从IN单元读入计数初值 $P 01 00 $P 02 61 ;LDI R1,0FH $P 03 0F ;立即数0FH送R1 $P 04 14 ;AND R0,R1 得到R0低…

中国移动获得手机直连卫星通讯牌照:行业变革的催化剂 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025 年 11 月抗衰老精华液,修护精华液,保湿精华液 OEM/ODM 加工厂最新推荐,聚焦高端定制需求与全案交付能力!

据国际高端美妆供应链协会 2025 年 10 月发布的《功效型精华代加工定制服务报告》显示,抗衰老、修护、保湿类精华高端定制 OEM/ODM 需求同比增长 61%,但 45% 的品牌方反馈合作工厂存在 “定制方案单一、全案交付断层…

2025 年 11 月烟酰胺精华液,富勒烯精华液,液态精华液 OEM/ODM 加工厂最新推荐,精准检测与稳定性能深度解析!

据国际美妆检测协会 2025 年 10 月发布的《液态功效型精华代加工检测与稳定性报告》显示,烟酰胺、富勒烯、液态类精华 OEM/ODM 需求同比增长 55%,但 43% 的品牌方反馈合作工厂存在 “检测标准不统一、液态性能不稳定…

2025 年 11 月复合酸精华液,抗衰老精华液,抗氧化精华液 OEM/ODM 加工厂最新推荐,技术实力与市场口碑深度解析!

据国际美妆技术协会 2025 年 10 月发布的《功效型精华代加工技术与口碑报告》显示,复合酸、抗衰老、抗氧化类精华 OEM/ODM 需求同比增长 58%,但 44% 的品牌方反馈合作工厂存在 “核心技术薄弱、研发创新不足、市场口…