GoF 的 23 种设计模式的分类和功能

本文深入解析了Gang of Four (GoF) 设计模式的23种分类,包括创建型、结构型和行为型模式,并逐一介绍了每种模式的功能和应用场景。通过实例与博客链接,助你理解和实践设计模式在软件开发中的价值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先了解,什么是GoF

        GoF是设计模式的经典名著Design Patterns: Elements of Reusable Object-Oriented Software(中译本名为《设计模式——可复用面向对象软件的基础》)的四位作者,他们分为是:Elich Gamma、Richard Helm、Ralph Johnson、以及John Vlissides。这四个人常被称为Gang of Four, 即四人组,简称GoF。

纯代码Git地址:DesignPattern设计模式 - Git,可以的话点个星★★★★ 

 纯代码Git地址:DesignPattern设计模式 - Gitee,可以的话点个星★★★★ 

一. 23中设计模式的划分,根据目的来分

根据模式是用来完成什么工作来划分,这种方式可分为创建型模式结构型模式行为型模式 3 种。

  1. 创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。GoF 中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。
     
  2. 结构型模式:用于描述如何将类或对象按某种布局组成更大的结构,GoF 中提供了代理、适配器、桥接、装饰、外观、享元、组合等 7 种结构型模式。
     
  3. 行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。GoF 中提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等 11 种行为型模式。

二. 根据作用范围来分

根据模式是主要用于类上还是主要用于对象上来分,这种方式可分为类模式对象模式两种。

  1. 类模式:用于处理类与子类之间的关系,这些关系通过继承来建立,是静态的,在编译时刻便确定下来了。GoF中的工厂方法、(类)适配器、模板方法、解释器属于该模式。
     
  2. 对象模式:用于处理对象之间的关系,这些关系可以通过组合或聚合来实现,在运行时刻是可以变化的,更具动态性。GoF 中除了以上 4 种,其他的都是对象模式。

范围\目的

创建型模式

结构型模式

行为型模式

类模式

工厂方法

(类)适配器

模板方法解释器

对象模式

单例

代理

策略

(对象)适配器

命令

原型

桥接

职责链

装饰器

状态

抽象工厂

外观

观察者

享元

中介者

建造者

迭代器

组合

访问者

备忘录

三. GoF的23种设计模式的功能

前面说明了 GoF 的 23 种设计模式的分类,现在对各个模式的功能进行介绍。

  1. 单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。相关博客
     
  2. 原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。相关博客
     
  3. 工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。相关博客
     
  4. 抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。相关博客
     
  5. 建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。相关博客
     
  6. 代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。相关博客
     
  7. 适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。相关博客
     
  8. 桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。相关博客
     
  9. 装饰(Decorator)模式:动态的给对象增加一些职责,即增加其额外的功能。相关博客
     
  10. 外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。相关博客
     
  11. 享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。相关博客
     
  12. 组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。相关博客
     
  13. 模板方法(TemplateMethod)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。相关博客
     
  14. 策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。相关博客
     
  15. 命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。相关博客
     
  16. 职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。相关博客
     
  17. 状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。相关博客
     
  18. 观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。相关博客
     
  19. 中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。相关博客
     
  20. 迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。相关博客
     
  21. 访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。相关博客
     
  22. 备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。相关博客
  23. 解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。相关博客

如果大家在之后的学习中有什么不懂的,随时联系小黑。

我会尽快回复,并且帮助你们哟。

😘😘😘😘😘😘😘😘😘😘😘😘😘😘😘😘😘😘😘😘😘😘😘😘😘


😄爱你们的😚

希望大家:点赞,留言,关注咯~    
😘😘😘😘

唠家常

小黑的今日分享结束啦,小伙伴们你们get到了么,你们有没有更好的办法呢,可以评论区留言分享,也可以加小黑的QQ:841298494,大家一起进步

今日无推荐

<think>好的,用户之前问过Java线程池的参数实例,现在接着问核心线程数最大线程数怎么设定合理。我需要先回顾之前的回答,确保这次的内容连贯。之前已经详细介绍了线程池的七个参数,并给出了示例代码执行流程。现在用户更关注这两个关键参数的设置,可能是在实际项目中遇到了性能调优的问题,或者想优化现有的线程池配置。 用户可能是开发人员,正在处理多线程任务,需要根据不同的任务类型来调整线程数。他们可能对CPU密集型IO密集型任务的区别不太清楚,或者不知道如何具体应用这些理论到实际中。需要给出具体的建议,比如公式或经验法则,同时结合场景说明。 需要确定核心线程数最大线程数的设置依据。根据常见的实践,CPU密集型任务通常设置为CPU核心数+1,而IO密集型则可能需要更多线程,比如2倍核心数。但用户可能想知道更详细的解释,比如为什么这样设置,或者是否有动态调整的方法。 另外,用户可能关心如何避免资源耗尽OOM问题,所以需要提到队列的选择拒绝策略的配合。比如,使用有界队列防止任务无限堆积,或者根据任务特性选择不同的队列类型。 还要考虑是否要介绍监控动态调整的方法,比如Spring的ThreadPoolTaskExecutor,或者Hystrix的线程池配置,但可能超出当前问题的范围。不过可以简要提及,让用户知道有这些工具可用。 需要结构清晰,分点说明,可能包括任务类型分析、参数设置公式、注意事项、示例场景等。同时结合之前的回答,保持一致性,比如之前提到的参数设置建议,这里需要详细展开核心最大线程数的部分。 需要验证下是否有最新的最佳实践,或者是否有不同的观点,比如是否核心线程数等于最大线程数在某些情况下更合适。比如在响应式编程或异步处理中,可能采用不同的策略。 还要注意避免过于技术化的术语,用通俗的中文解释清楚。比如解释CPU密集型任务为什么需要较少的线程,IO密集型为什么可以更多,因为线程在等待IO时可以释放CPU资源。 最后,给出一个总结性的建议,帮助用户快速决策,同时提醒他们实际测试的重要性,因为理论值可能需要根据具体环境调整。</think>在Java线程池中,核心线程数(`corePoolSize`)最大线程数(`maximumPoolSize`)的设置直接影响系统性能资源利用率。以下是结合不同场景的详细设定建议: --- ### 一、基础公式与原则 | 参数 | 作用 | 设置原则 | |----------------|-----------------------------------|-----------------------------------| | 核心线程数 | 长期保留的线程,处理常规任务 | **不低于最低需求**,避免频繁创建/销毁 | | 最大线程数 | 应对突发流量的临时线程 | **不高于系统承载极限**,防止资源耗尽 | --- ### 二、按任务类型划分 #### 1. **CPU密集型任务** 特点:大量计算(如算法运算、数值分析) 公式: $$ \text{核心线程数} = \text{CPU核心数} + 1 $$ $$ \text{最大线程数} = \text{核心线程数} \quad \text{或} \quad \text{核心数} \times 1.5 $$ 示例: ```java // 8核CPU处理视频转码任务 int core = Runtime.getRuntime().availableProcessors() + 1; // 9 int max = core; // 保持与核心数一致 ``` #### 2. **IO密集型任务** 特点:频繁等待(如数据库操作、网络请求) 公式: $$ \text{核心线程数} = \text{CPU核心数} \times 2 $$ $$ \text{最大线程数} = \text{核心数} \times (2 \sim 5) $$ 示例: ```java // 8核CPU处理HTTP请求 int core = Runtime.getRuntime().availableProcessors() * 2; // 16 int max = core * 3; // 48 ``` #### 3. **混合型任务** 策略: - 拆分为CPU/IO两种线程池分别处理 - 使用动态调整策略: $$ \text{最大线程数} = \frac{\text{任务总耗时}}{\text{CPU计算耗时}} \times \text{核心数} $$ --- ### 三、高级调整策略 #### 1. **利特尔法则(Little's Law)** 适用于需要控制响应时间的场景: $$ \text{线程数} = \frac{\text{平均响应时间} + \text{平均等待时间}}{\text{平均响应时间}} \times \text{CPU核心数} $$ #### 2. **动态调整(适用云原生场景)** ```java ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool(); executor.setCorePoolSize(动态值); // 根据监控指标实时调整 executor.setMaximumPoolSize(动态值); ``` #### 3. **Spring Boot实践建议** ```yaml # application.yml task: execution: pool: core-size: 8 max-size: 20 queue-capacity: 100 ``` --- ### 四、关键注意事项 1. **队列容量与线程数的平衡** - 大队列+小线程数:适合短任务、高吞吐场景 - 小队列+大线程数:适合长任务、低延迟场景 2. **避免典型误区** - ❌ 核心线程数=0:导致频繁创建/销毁线程 - ❌ 最大线程数=Integer.MAX_VALUE:引发OOM风险 - ❌ 核心线程数=最大线程数:失去应对突发流量的能力 3. **监控指标参考** | 指标 | 健康值域 | 干预措施 | |-----------------------|-------------------|-----------------------------------| | 活跃线程数 / 最大线程数 | < 80% | 正常 | | 队列使用率 | < 90% | 扩容队列或线程数 | | 拒绝任务数 | =0 | 优化拒绝策略或扩容 | --- ### 五、真实场景案例 #### 电商秒杀系统(突发流量) ```java // 16核服务器配置 int core = 16; // 基础承载能力 int max = 16 * 5; // 应对瞬时流量(80线程) BlockingQueue queue = new LinkedBlockingQueue(500); // 缓冲队列 // 配合拒绝策略:队列满时返回错误提示 RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); ``` #### 数据分析后台(稳定负载) ```java // 32核服务器处理批量计算 int core = 32 + 1 = 33; int max = 33; // 保持固定线程数 BlockingQueue queue = new ArrayBlockingQueue(1000); // 有序队列 ``` --- ### 六、验证工具推荐 1. **JVisualVM**:监控线程状态CPU使用率 2. **Arthas**:实时查看线程池运行状态 ```bash thread -n 5 # 查看最忙的5个线程 dashboard # 监控线程池队列情况 ``` 3. **Prometheus + Grafana**:搭建可视化监控平台 --- 合理设置线程数的本质是在**资源利用率****系统稳定性**之间找到平衡点。建议先通过公式计算理论值,再结合压力测试(如JMeter)逐步优化,最终以实际监控数据为准动态调整。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青衫磊落长歌行

觉得小黑这篇文章不赖,打赏哟~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值