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

news2025/1/12 8:37:59

目录

  • 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 {
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
}
// 具体产品类 - 矩形
class Rectangle implements Shape {
    @Override
    public 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;
    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }
    @Override
    public void removeObserver(Observer o) {
        observers.remove(o);
    }
    @Override
    public 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;
    }
    @Override
    public 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;
    }
    @Override
    public double calculateDiscount(double price) {
        return price * discountRate;
    }
}
// 具体策略 - 固定金额折扣
class FixedAmountDiscount implements DiscountStrategy {
    private double fixedDiscount;
    public FixedAmountDiscount(double fixedDiscount) {
        this.fixedDiscount = fixedDiscount;
    }
    @Override
    public 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 {
    @Override
    public 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);
    }
    @Override
    public double cost() {
        return beverage.cost() + 1.0;
    }
}
// 具体装饰器 - 焦糖
class CaramelDecorator extends CondimentDecorator {
    public CaramelDecorator(Beverage beverage) {
        super(beverage);
    }
    @Override
    public 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、内存、硬盘、操作系统等),可以通过外观模式提供一个简单的“启动计算机”的接口,将内部复杂的操作封装起来,方便用户使用。

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

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

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

相关文章

分布式搜索引擎之elasticsearch单机部署与测试

分布式搜索引擎之elasticsearch单机部署与测试 1.部署单点es 1.1.创建网络 因为我们还需要部署kibana容器&#xff0c;因此需要让es和kibana容器互联。这里先创建一个网络&#xff1a; docker network create es-net1.2.加载镜像 这里我们采用elasticsearch的7.12.1版本的…

【工具】JS解析XML并且转为json对象

【工具】JS解析XML并且转为json对象 <?xml version1.0 encodingGB2312?> <root><head><transcode>hhhhhhh</transcode></head><body><param>ccccccc</param><param>aaaaaaa</param><param>qqqq<…

CSDN设置成黑色背景(谷歌 Edge)

一.谷歌浏览器 浏览器地址输入&#xff1a;Chrome://flags搜索框输入&#xff1a;enable-force-dark将default 改成 enabled&#xff0c;点击重启浏览器 二.Edge浏览器 浏览器地址输入&#xff1a;edge://flags搜索里面输入Auto Dark Mode for Web Contents将default 改成 e…

【动手学电机驱动】STM32-FOC(8)MCSDK Profiler 电机参数辨识

STM32-FOC&#xff08;1&#xff09;STM32 电机控制的软件开发环境 STM32-FOC&#xff08;2&#xff09;STM32 导入和创建项目 STM32-FOC&#xff08;3&#xff09;STM32 三路互补 PWM 输出 STM32-FOC&#xff08;4&#xff09;IHM03 电机控制套件介绍 STM32-FOC&#xff08;5&…

OGRE 3D----3. OGRE绘制自定义模型

在使用OGRE进行开发时,绘制自定义模型是一个常见的需求。本文将介绍如何使用OGRE的ManualObject类来创建和绘制自定义模型。通过ManualObject,开发者可以直接定义顶点、法线、纹理坐标等,从而灵活地构建各种复杂的几何体。 Ogre::ManualObject 是 Ogre3D 引擎中的一个类,用…

【网络安全 | 漏洞挖掘】绕过SAML认证获得管理员面板访问权限

未经许可,不得转载。 文章目录 什么是SAML认证?SAML是如何工作的?SAML响应结构漏洞结果什么是SAML认证? SAML(安全断言标记语言)用于单点登录(SSO)。它是一种功能,允许用户在多个服务之间切换时无需多次登录。例如,如果你已经登录了facebook.com,就不需要再次输入凭…

AI自动化剪辑工具:可将长视频中精彩部分提取合成短视频

最近&#xff0c;我发现了一款特别适合当下短视频潮流的自动化工具&#xff0c;它能够让我们轻松从长视频中剪辑出精彩片段&#xff0c;并快速生成适合分享的短视频。 这款工具叫 AI Youtube Shorts Generator&#xff0c;是一个开源项目&#xff0c;特别适合那些喜欢制作短视…

Windsurf可以上传图片开发UI了

背景 曾经羡慕Cursor的“画图”开发功能&#xff0c;这不Windsurf安排上了。 Upload Images to Cascade Cascade now supports uploading images on premium models Ask Cascade to build or tweak UI from on image upload New keybindings Keybindings to navigate betwe…

(二)Sping Boot学习——Sping Boot注意事项

1.springboot默认是扫描的类是在启动类的当前包或者下级包。 2.运行报错 ERROR&#xff1a;An incompatible version [1.2.33] of the Apache Tomcat Native library is installed, while Tomcat requires version [1.2.34] 网上试了很多方法&#xff0c;直接重新安装更新版…

Elasticsearch:Retrievers 介绍

检索器&#xff08;retrievers&#xff09;是 Elasticsearch 中搜索 API 中添加的新抽象层。它们提供了在单个 _search API 调用中配置多阶段检索管道的便利。此架构通过消除对复杂搜索查询的多个 Elasticsearch API 调用的需求&#xff0c;简化了应用程序中的搜索逻辑。它还减…

Ubuntu下的Doxygen+VScode实现C/C++接口文档自动生成

Ubuntu下的DoxygenVScode实现C/C接口文档自动生成 1、 Doxygen简介 Doxygen 是一个由 C 编写的、开源的、跨平台的文档生成系统。最初主要用于生成 C 库的 API 文档&#xff0c;但目前又添加了对 C、C#、Java、Python、Fortran、PHP 等语言的支持。其从源代码中提取注释&…

Css—实现3D导航栏

一、背景 最近在其他的网页中看到了一个很有趣的3d效果&#xff0c;这个效果就是使用css3中的3D转换实现的&#xff0c;所以今天的内容就是3D的导航栏效果。那么话不多说&#xff0c;直接开始主要内容的讲解。 二、效果展示 三、思路解析 1、首先我们需要将这个导航使用一个大…

快速理解微服务中Fegin的概念

一.由来 1.在传统的架构里面&#xff0c;我们是通过使用RestTemplate来访问其他的服务&#xff0c;但是这种方式就存在了一个很大的缺陷&#xff0c;也就是被调用方如果发生了服务的迁移(IP和端口发生了变化)&#xff0c;那么调用方也需要同步的在代码里面进行修改&#xff0c;…

【Git】Git 完全指南:从入门到精通

Git 完全指南&#xff1a;从入门到精通 Git 是现代软件开发中最重要的版本控制工具之一&#xff0c;它帮助开发者高效地管理项目&#xff0c;支持分布式协作和版本控制。无论是个人项目还是团队开发&#xff0c;Git 都能提供强大的功能来跟踪、管理代码变更&#xff0c;并保障…

Spring Web MVC(详解中)

文章目录 Spring MVC&#xff08;中&#xff09;RESTFul风格设计RESTFul风格概述RESTFul风格特点RESTFul风格设计规范RESTFul风格好处RESTFul风格实战需求分析RESTFul风格接口设计后台接口实现 基于RESTFul风格练习&#xff08;前后端分离模式&#xff09;案例功能和接口分析功…

什么是GAN?

一、基本概念 生成对抗网络&#xff08;Generative Adversarial Network&#xff0c;GAN&#xff09;是一种由两个神经网络共同组成深度学习模型&#xff1a;生成器&#xff08;Generator&#xff09;和判别器&#xff08;Discriminator&#xff09;。这两个网络通过对抗的方式…

Spring |(八)AOP配置管理

文章目录 &#x1f4da;AOP切点表达式&#x1f407;语法格式&#x1f407;通配符 &#x1f4da;AOP通知类型&#x1f407;环境准备&#x1f407;通知类型的使用 &#x1f4da;AOP通知获取数据&#x1f407;环境准备&#x1f407;获取参数&#x1f407;获取返回值&#x1f407;获…

Flink 从入门到实战

Flink中的批和流 批处理的特点是有界、持久、大量&#xff0c;非常适合需要访问全部记录才能完成的计算工作&#xff0c;一般用于离线统计。 流处理的特点是无界、实时, 无需针对整个数据集执行操作&#xff0c;而是对通过系统 传输的每个数据项执行操作&#xff0c;一般用于实…

Ubuntu20.04运行LARVIO

文章目录 1.运行 Toyish 示例程序2.运行 ROS Nodelet参考 1.运行 Toyish 示例程序 LARVIO 提供了一个简化的toyish示例程序&#xff0c;适合快速验证和测试。 编译项目 进入 build 文件夹并通过 CMake 编译项目&#xff1a; mkdir build cd build cmake -D CMAKE_BUILD_TYPER…

小程序-基于java+SpringBoot+Vue的戏曲文化苑小程序设计与实现

项目运行 1.运行环境&#xff1a;最好是java jdk 1.8&#xff0c;我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境&#xff1a;IDEA&#xff0c;Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境&#xff1a;Tomcat 7.x,8.x,9.x版本均可 4.硬件环境&#xff1a…