当前位置: 首页 > news >正文

Java基础 设计模式——针对实习面试

目录

  • Java基础 设计模式
    • 单例模式
    • 工厂模式
    • 观察者模式
    • 策略模式
    • 装饰器模式
    • 其他设计模式

Java基础 设计模式

在这里插入图片描述

单例模式

  1. 单例模式(Singleton Pattern)
    • 定义:确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。
    • 适用场景
      • 当系统中某个类只需要一个实例,如数据库连接池。因为频繁地创建和销毁数据库连接是非常消耗资源的,使用单例模式可以保证整个应用程序中只有一个数据库连接池实例,所有需要数据库连接的地方都从这个实例获取连接。
      • 配置文件管理器,整个应用程序通常只需要一个配置文件管理器来读取和管理配置信息。
    • 示例代码(懒汉式单例)
class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}
  • 解释:在上述代码中,Singleton类的构造函数是私有的,这样就防止了其他类直接通过new关键字来创建Singleton类的实例。getInstance方法是获取单例对象的公共方法,当instancenull时,创建一个新的Singleton实例,然后返回这个实例。不过这种懒汉式单例在多线程环境下可能会出现问题,因为可能会有多个线程同时判断instancenull,从而创建多个实例。可以通过加锁等方式解决这个问题,比如使用双重检查锁定(DCL - Double - Checked Locking)。

工厂模式

  1. 工厂模式(Factory Pattern)
    • 定义:定义一个创建对象的接口,但让子类决定实例化哪个类。工厂模式把对象的创建和使用分离。
    • 适用场景
      • 当对象的创建过程比较复杂,比如创建对象需要读取配置文件、连接数据库等操作时。例如,在一个游戏开发中,游戏角色有多种类型(战士、法师、刺客),不同类型的角色初始化过程不同,使用工厂模式可以将角色创建过程封装在工厂类中。
      • 根据不同条件创建不同类型的对象。例如,在一个图形绘制系统中,根据用户选择绘制不同的图形(圆形、矩形、三角形),可以使用工厂模式来创建这些图形对象。
    • 示例代码(简单工厂模式)
// 产品接口
interface Shape {void draw();
}
// 具体产品类 - 圆形
class Circle implements Shape {@Overridepublic void draw() {System.out.println("Drawing a circle");}
}
// 具体产品类 - 矩形
class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Drawing a rectangle");}
}
// 工厂类
class ShapeFactory {public Shape getShape(String shapeType) {if (shapeType.equalsIgnoreCase("circle")) {return new Circle();} else if (shapeType.equalsIgnoreCase("rectangle")) {return new Rectangle();}return null;}
}
  • 解释Shape是产品接口,CircleRectangle是具体的产品类,它们实现了draw方法。ShapeFactory是工厂类,getShape方法根据传入的shapeType字符串来决定创建哪种具体的形状对象。这样,当需要创建形状对象时,只需要调用工厂类的getShape方法,而不需要关心具体对象的创建细节。

观察者模式

  1. 观察者模式(Observer Pattern)
    • 定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
    • 适用场景
      • 消息推送系统,当有新的消息产生时,所有订阅了该消息类型的用户(观察者)都会收到通知。例如,在一个新闻发布系统中,当有新的新闻发布时,订阅了该新闻频道的用户会收到更新通知。
      • GUI编程中的事件处理,例如按钮点击事件。当按钮(被观察对象)被点击时,所有注册到这个按钮的事件监听器(观察者)都会收到通知并执行相应的操作。
    • 示例代码
import java.util.ArrayList;
import java.util.List;
// 被观察主题接口
interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers();
}
// 观察者接口
interface Observer {void update(String message);
}
// 具体被观察主题 - 消息发布者
class MessagePublisher implements Subject {private List<Observer> observers = new ArrayList<>();private String message;@Overridepublic void registerObserver(Observer o) {observers.add(o);}@Overridepublic void removeObserver(Observer o) {observers.remove(o);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(message);}}public void setMessage(String message) {this.message = message;notifyObservers();}
}
// 具体观察者 - 用户
class User implements Observer {private String name;public User(String name) {this.name = name;}@Overridepublic void update(String message) {System.out.println(name + " received message: " + message);}
}
  • 解释Subject是被观察主题接口,定义了注册观察者、移除观察者和通知观察者的方法。Observer是观察者接口,update方法用于接收被观察对象的状态更新消息。MessagePublisher是具体的被观察主题,它维护了一个观察者列表,当消息更新(通过setMessage方法)时,会遍历观察者列表并调用每个观察者的update方法。User是具体的观察者,实现了update方法来处理接收到的消息。

策略模式

  1. 策略模式(Strategy Pattern)
    • 定义:定义一系列算法,将每个算法封装起来,并使它们可以相互替换。策略模式让算法的变化独立于使用它的客户。
    • 适用场景
      • 电商系统中的折扣计算。例如,在促销活动中,可能有不同的折扣策略,如满减折扣、百分比折扣、固定金额折扣等。可以将这些折扣计算方法封装成不同的策略类,根据不同的促销活动选择合适的策略。
      • 排序算法的选择。系统中有多种排序算法(冒泡排序、快速排序、归并排序),根据数据的特点和性能要求选择不同的排序策略。
    • 示例代码
// 策略接口
interface DiscountStrategy {double calculateDiscount(double price);
}
// 具体策略 - 百分比折扣
class PercentageDiscount implements DiscountStrategy {private double discountRate;public PercentageDiscount(double discountRate) {this.discountRate = discountRate;}@Overridepublic double calculateDiscount(double price) {return price * discountRate;}
}
// 具体策略 - 固定金额折扣
class FixedAmountDiscount implements DiscountStrategy {private double fixedDiscount;public FixedAmountDiscount(double fixedDiscount) {this.fixedDiscount = fixedDiscount;}@Overridepublic double calculateDiscount(double price) {return fixedDiscount;}
}
// 上下文类
class ShoppingCart {private DiscountStrategy discountStrategy;public ShoppingCart(DiscountStrategy discountStrategy) {this.discountStrategy = discountStrategy;}public double calculateTotalDiscount(double price) {return discountStrategy.calculateDiscount(price);}
}
  • 解释DiscountStrategy是策略接口,定义了calculateDiscount方法用于计算折扣。PercentageDiscountFixedAmountDiscount是具体的策略类,分别实现了百分比折扣和固定金额折扣的计算方法。ShoppingCart是上下文类,它包含一个DiscountStrategy类型的成员变量,通过构造函数注入具体的策略对象,calculateTotalDiscount方法使用注入的策略对象来计算折扣。这样,当需要改变折扣策略时,只需要创建不同的策略对象并注入到ShoppingCart中即可。

装饰器模式

  1. 装饰器模式(Decorator Pattern)
    • 定义:动态地给一个对象添加一些额外的职责。就扩展功能而言,它比继承更灵活。
    • 适用场景
      • 给一个基本的输入/输出流添加缓冲、加密等功能。例如,在文件读取时,可能先需要对文件内容进行缓冲读取(BufferedInputStream),也可能需要对读取的内容进行加密处理(自定义加密装饰器),可以使用装饰器模式来动态地添加这些功能。
      • 咖啡店的饮品定制。一杯咖啡(基本饮品)可以添加奶泡、焦糖、香草等配料(装饰)来定制口味,每种配料都可以看作是一个装饰器,通过不断地添加装饰器来实现不同的饮品组合。
    • 示例代码(简单的饮品装饰器示例)
// 饮品接口
interface Beverage {double cost();
}
// 具体饮品 - 咖啡
class Coffee implements Beverage {@Overridepublic double cost() {return 5.0;}
}
// 装饰器抽象类
abstract class CondimentDecorator implements Beverage {protected Beverage beverage;public CondimentDecorator(Beverage beverage) {this.beverage = beverage;}
}
// 具体装饰器 - 奶泡
class MilkFoamDecorator extends CondimentDecorator {public MilkFoamDecorator(Beverage beverage) {super(beverage);}@Overridepublic double cost() {return beverage.cost() + 1.0;}
}
// 具体装饰器 - 焦糖
class CaramelDecorator extends CondimentDecorator {public CaramelDecorator(Beverage beverage) {super(beverage);}@Overridepublic double cost() {return beverage.cost() + 0.5;}
}
  • 解释Beverage是饮品接口,定义了cost方法用于计算饮品价格。Coffee是具体的饮品类。CondimentDecorator是装饰器抽象类,它实现了Beverage接口并且包含一个Beverage类型的成员变量,用于保存被装饰的饮品对象。MilkFoamDecoratorCaramelDecorator是具体的装饰器类,它们在cost方法中先调用被装饰饮品的cost方法,然后再加上自己添加的配料的价格。这样,就可以通过不断地用装饰器包装饮品对象来动态地添加功能和计算价格。例如,MilkFoamDecorator(new CaramelDecorator(new Coffee())).cost()这样的调用就可以计算出一杯加了奶泡和焦糖的咖啡的价格。

其他设计模式

上文五种设计模式是比较常用的,但很难绝对地说它们是“最常用”的。

  1. 从使用频率角度看

    • 在实际的软件开发中,单例模式用于管理共享资源,如日志系统、配置管理器等,其使用频率较高。许多框架和应用程序都需要确保某些关键对象在整个生命周期内只有一个实例,以保证资源的有效利用和数据的一致性。
    • 工厂模式有助于解耦对象的创建和使用,在对象创建过程复杂或者需要根据不同条件创建不同对象的场景下被广泛应用。比如在大型企业级应用开发中,经常会用到工厂模式来创建各种业务对象。
    • 观察者模式在事件驱动的编程场景下非常实用,像图形用户界面(GUI)开发、消息队列系统等领域大量使用。随着软件系统的交互性越来越复杂,观察者模式的应用也越来越广泛。
    • 策略模式用于实现算法的灵活替换,在需要根据不同情况选择不同算法或行为的场景下发挥重要作用。例如在金融系统中计算利息的不同策略,或者游戏中角色行为的不同策略选择等场景经常会用到。
    • 装饰器模式对于动态地扩展对象功能很有帮助,在Java的输入/输出流处理以及一些具有可定制功能的对象设计中较为常用,如Web开发中的请求和响应处理,也可以通过装饰器模式来添加诸如缓存、安全验证等额外功能。
  2. 其他常用的设计模式还有

    • 代理模式(Proxy Pattern)
      • 适用场景
        • 远程代理,用于代表一个远程对象,隐藏网络通信等细节。例如,在分布式系统中,一个本地对象代表远程服务器上的对象进行方法调用,通过网络通信获取远程对象的数据或执行远程对象的操作。
        • 虚拟代理,用于延迟加载资源。比如,在网页加载图片时,如果图片很大,可以先使用一个占位符(虚拟代理)显示,当真正需要显示图片细节时(比如图片进入可视区域),再加载实际的图片资源。
    • 模板方法模式(Template Method Pattern)
      • 适用场景
        • 框架开发中,定义算法的骨架,让子类去实现某些具体步骤。例如,在一个游戏开发框架中,游戏的启动流程(加载资源、初始化场景、开始游戏循环等)可以通过模板方法模式定义,不同类型的游戏(如角色扮演游戏、射击游戏)可以继承这个模板并实现自己特定的加载资源和初始化场景的方式。
    • 外观模式(Facade Pattern)
      • 适用场景
        • 用于为复杂的子系统提供一个简单统一的接口。例如,在一个计算机系统中,启动计算机涉及到多个硬件设备和软件系统的启动和初始化(CPU、内存、硬盘、操作系统等),可以通过外观模式提供一个简单的“启动计算机”的接口,将内部复杂的操作封装起来,方便用户使用。

这几种设计模式也都有各自特定的适用场景,在很多软件系统的设计和开发中都发挥着重要作用。具体哪种设计模式最常用,还会因不同的业务领域、软件规模、开发团队的习惯等因素而有所不同。

相关文章:

Java基础 设计模式——针对实习面试

目录 Java基础 设计模式单例模式工厂模式观察者模式策略模式装饰器模式其他设计模式 Java基础 设计模式 单例模式 单例模式&#xff08;Singleton Pattern&#xff09; 定义&#xff1a;确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问这个实例。适用场景&…...

最大公约数和最小公倍数-多语言

目录 C 语言实现 Python 实现 Java 实现 Js 实现 题目&#xff1a;输入两个正整数m和n&#xff0c;求其最大公约数和最小公倍数。 程序分析&#xff1a; 最小公倍数输入的两个数之积除于它们的最大公约数&#xff0c;关键是求出最大公约数&#xff1b; 求最大公约数用辗转…...

第三方数据库连接免费使用和安装

是强大的一体化数据库开发解决方案&#xff0c;可从单一应用程序无缝连接多个数据库&#xff0c;包括 MySQL、PostgreSQL、MongoDB、MariaDB、SQL Server、Oracle、SQLite 和 Redis。 下载&#xff1a;https://download.csdn.net/download/mo3408/90045937 升级特性 模型&…...

水库大坝安全监测之量水堰计应用

量水堰计是水库大坝安全监测系统中的一种关键设备&#xff0c;主要用于测量水库水位、流量等水力参数。以下是量水堰计在水库大坝安全监测中的应用及注意事项&#xff1a; 一、量水堰计的工作原理 量水堰计是一种专门用于测量水流流量的仪器&#xff0c;其工作原理主要基于水流…...

算法笔记:滑动窗口

前言 滑动窗口作为一个考点较高的算法&#xff0c;广泛应用于子串问题中&#xff0c;本文将进行详细讲解。 一、滑动窗口是什么 滑动窗口是双指针算法的一种&#xff0c;基本思路为维护一个窗口&#xff0c;然后从前往后遍历元素进行运算。 二、滑动窗口算法和其他双指针算…...

Ubuntu下的Graphviz的基础使用方法

一、Graphviz介绍 graphviz是贝尔实验室开发的一个开源的工具包&#xff0c;它使用一个特定的DSL(领域特定语言):dot作为脚本语言&#xff0c;然后使用布局引擎来解析此脚本&#xff0c;并完成自动布局 1、什么是Graphviz 官网地址&#xff0c;https://www.graphviz.org/ Gr…...

微积分复习笔记 Calculus Volume 1 - 6.8 Exponential Growth and Decay

6.8 Exponential Growth and Decay - Calculus Volume 1 | OpenStax...

React的ts文件中通过createElement拼接一段内容出来

比如接口返回一个值 const values [23.00, 40.00/kg];想做到如下效果&#xff0c; 如果单纯的用render渲染会很简单&#xff0c; 但是在ts文件中处理&#xff0c;所以采用了createElement拼接 代码如下&#xff1a; format: (values: string[]) > {if (!values || !val…...

Pinia之1:介绍Pinia、项目中引入Pinia

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…...

Python双向链表、循环链表、栈

一、双向链表 1.作用 双向链表也叫双面链表。 对于单向链表而言。只能通过头节点或者第一个节点出发&#xff0c;单向的访问后继节点&#xff0c;每个节点只能记录其后继节点的信息&#xff08;位置&#xff09;&#xff0c;不能向前遍历。 所以引入双向链表&#xff0c;双…...

5G基础学习笔记

功能软件化 刚性网络&#xff1a;固定连接、固定功能、固化信令交互 柔性网络&#xff1a;网元拆解成服务模块&#xff0c;基于API接口调用 服务化架构&#xff08;SBA&#xff09; Service based Architecture &#xff08;SBA&#xff09;: 借鉴了业界成熟的SOA、微服务架…...

Python plotly库介绍

一、引言 在数据可视化领域&#xff0c;Python提供了众多强大的库。其中&#xff0c;plotly是一个功能强大、交互式的可视化库&#xff0c;可以创建各种类型的图表&#xff0c;包括线图、散点图、柱状图、饼图、3D图表等。它不仅提供了美观的可视化效果&#xff0c;还支持交互式…...

go编程中yaml的inline应用

下列代码&#xff0c;设计 Config 和 MyConfig 是为可扩展 Config&#xff0c;同时 Config 作为公共部分可保持变化。采用了匿名的内嵌结构体&#xff0c;但又不希望 yaml 结果多出一层。如果 MyConfig 中的 Config 没有使用“yaml:",inline"”修饰&#xff0c;则读取…...

手机实时提取SIM卡打电话的信令声音-智能拨号器的双SIM卡切换方案

手机实时提取SIM卡打电话的信令声音 --智能拨号器app的双SIM卡切换方案 一、前言 在蓝牙电话的方案中&#xff0c;由于采用市场上的存量手机来做为通讯呼叫的载体&#xff0c;而现在市面上大部分的手机都是“双卡双待单通”手机&#xff0c;简称双卡双待手机。即在手机开机后…...

探索Python WebSocket新境界:picows库揭秘

文章目录 探索Python WebSocket新境界&#xff1a;picows库揭秘第一部分&#xff1a;背景介绍第二部分&#xff1a;picows库概述第三部分&#xff1a;安装picows库第四部分&#xff1a;简单库函数使用方法第五部分&#xff1a;场景应用第六部分&#xff1a;常见Bug及解决方案第…...

2024年11月24日Github流行趋势

项目名称&#xff1a;FreeCAD 项目维护者&#xff1a;wwmayer, yorikvanhavre, berndhahnebach, chennes, WandererFan等项目介绍&#xff1a;FreeCAD是一个免费且开源的多平台3D参数化建模工具。项目star数&#xff1a;20,875项目fork数&#xff1a;4,117 项目名称&#xff1…...

NewStar CTF week5 Crypto wp

easy_ecc ecc的模板题&#xff0c;稍加推理就会发现c1mc2*k因此做一个减法就行&#xff0c;需要注意的点是c1,c2必须放到ecc里面过一道才能出正确结果 k 86388708736702446338970388622357740462258632504448854088010402300997950626097 p 644088904089909773124499208053…...

vue3+antd注册全局v-loading指令

文章目录 1. 创建指令文件2. 全局注册3. 使用 1. 创建指令文件 src/directives 在directives中创建如下文件 src│─directives│ index.ts└─loadingindex.tsindex.vuedirectives/ index.ts export * from ./loadingdirectives/loading/index.ts import { createApp } f…...

初试无监督学习 - K均值聚类算法

文章目录 1. K均值聚类算法概述2. k均值聚类算法演示2.1 准备工作2.2 生成聚类用的样本数据集2.3 初始化KMeans模型对象&#xff0c;并指定类别数量2.4 用样本数据训练模型2.5 用训练好的模型生成预测结果2.6 输出预测结果2.7 可视化预测结果 3. 实战小结 1. K均值聚类算法概述…...

捉虫笔记(七)-再探谁把系统卡住了

捉虫笔记&#xff08;七&#xff09;-再探谁把系统卡住 1、内核调试 在实体物理机上&#xff0c;内核调试的第一个门槛就是如何建立调试链接。 这里我选择的建立网络连接进行内核调试。 至于如何建立网络连接后续文章再和大家分享。 2、如何分析 在上一篇文章中&#xff0c;我们…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…...

Qt 事件处理中 return 的深入解析

Qt 事件处理中 return 的深入解析 在 Qt 事件处理中&#xff0c;return 语句的使用是另一个关键概念&#xff0c;它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别&#xff1a;不同层级的事件处理 方…...