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 {
    @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、内存、硬盘、操作系统等),可以通过外观模式提供一个简单的“启动计算机”的接口,将内部复杂的操作封装起来,方便用户使用。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QRCode.toDataURL() vue3 uniapp h5在 Android环境下二维码显示不出来

“qrcode”: “^1.5.4” 修改前&#xff08;在浏览器里面是可以加载的&#xff09;&#xff1a; 查资料好像是Android上加载的是canvas&#xff0c;不是加载的img。 修改后&#xff1a; 这里val其实打印出来是svg代码&#xff0c;所以用v-html就好了。

数据结构——排序算法第一幕(插入排序:直接插入排序、希尔排序 选择排序:直接选择排序,堆排序)超详细!!!!

文章目录 前言一、排序1.1 概念1.2 常见的排序算法 二、插入排序2.1 直接插入排序2.2 希尔排序希尔排序的时间复杂度 三、选择排序3.1 直接选择排序3.2 堆排序 总结 前言 时间很快&#xff0c;转眼间已经到数据结构的排序算法部分啦 今天我们来学习排序算法当中的 插入排序 和 …

第32周:猴痘病识别(Tensorflow实战第四周)

目录 前言 一、前期工作 1.1 设置GPU 1.2 导入数据 1.3 查看数据 二、数据预处理 2.1 加载数据 2.2 可视化数据 2.3 再次检查数据 2.4 配置数据集 2.4.1 基本概念介绍 2.4.2.代码完成 三、构建CNN网络 四、编译 五、训练模型 六、模型评估 6.1 Loss和Accuracy…

【创建型设计模式】工厂模式

【创建型设计模式】工厂模式 创建型设计模式第二期&#xff01;本期介绍简单工厂模式和工厂方法模式。 简单工厂模式 简单工厂模式&#xff08;又叫作静态工厂方法模式&#xff09;&#xff0c;其属于创建型设计模式&#xff0c;简单工厂模式不属于设计模式中的 23 种经典模…

【Linux】安装cuda

一、安装nvidia驱动 # 添加nvidia驱动ppa库 sudo add-apt-repository ppa:graphics-drivers/ppa sudo apt update# 查找推荐版本 sudo ubuntu-drivers devices# 安装推荐版本 sudo apt install nvidia-driver-560# 检验nvidia驱动是否安装 nvidia-smi 二、安装cudatoolkit&…

上天入地 灵途科技光电技术赋能空间感知

近来&#xff0c;人工智能技术频频亮相各大马拉松赛事&#xff0c;成为引人注目的科技亮点。 11月3日&#xff0c;杭州马拉松首次启用了机器狗作为配速员&#xff0c;以稳定的节奏为选手提供科学的跑步节奏。 11月11日&#xff0c;亦庄半程马拉松的终点处&#xff0c;人形机器…

Java三大特性:封装、继承、多态【详解】

封装 定义 隐藏对象的属性和实现细节&#xff0c;仅对外公开接口&#xff0c;控制在程序中属性的读取和修改的访问级别便是封装。 在开发中造一个类就是封装&#xff0c;有时也会说封装一个类。封装可以隐藏一些细节或者包含数据不能被随意修改。 比如这是一个敏感的数据&a…

40分钟学 Go 语言高并发:【实战】并发安全的配置管理器(功能扩展)

【实战】并发安全的配置管理器&#xff08;功能扩展&#xff09; 一、扩展思考 分布式配置中心 实现配置的集中管理支持多节点配置同步实现配置的版本一致性 配置加密 敏感配置的加密存储配置的安全传输访问权限控制 配置格式支持 支持YAML、TOML等多种格式配置格式自动…

【ChatGPT大模型开发调用】如何获得 OpenAl API Key?

如何获取 OpenAI API Key 获取 OpenAI API Key 主要有以下三种途径&#xff1a; OpenAI 官方平台 (推荐): 开发者用户可以直接在 OpenAI 官方网站 (platform.openai.com) 注册并申请 API Key。 通常&#xff0c;您可以在账户设置或开发者平台的相关页面找到申请入口。 Azure…

苹果系统中利用活动监视器来终止进程

前言 苹果系统使用的时候总是感觉不太顺手。特别是转圈的彩虹球出现的时候&#xff0c;就非常令人恼火。如何找到一个像Windows那样任务管理器来终止掉进程呢&#xff1f; 解决办法 Commandspace 弹出搜索框吗&#xff0c;如下图&#xff1a; 输入“活动”进行搜索&#xff…

实战项目负载均衡式在线 OJ

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;能自己实现负载均衡式在线 OJ。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! > 专栏选自&#xff1…

python Flask指定IP和端口

from flask import Flask, request import uuidimport json import osapp Flask(__name__)app.route(/) def hello_world():return Hello, World!if __name__ __main__:app.run(host0.0.0.0, port5000)

burp suite-1

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…

【Spring boot】微服务项目的搭建整合swagger的fastdfs和demo的编写

文章目录 1. 微服务项目搭建2. 整合 Swagger 信息3. 部署 fastdfsFastDFS安装环境安装开始图片测试FastDFS和nginx整合在Storage上安装nginxnginx安装不成功排查:4. springboot 整合 fastdfs 的demodemo编写1. 微服务项目搭建 版本总结: spring boot: 2.6.13springfox-boot…

【区块链】深入理解椭圆曲线密码学(ECC)

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 深入理解椭圆曲线密码学(ECC)1. 概述2. 椭圆曲线的数学基础2.1 基本定义2.2 有限…

【Qt流式布局改造支持任意位置插入和删除】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、源代码二、删除代码三、扩展总结 前言 最近在做一个需求需要流式布局&#xff0c;虽然官方example里有一个流式布局范例&#xff0c;但是不能满足我的需求…

JQuery -- 第九课

文章目录 前言一、JQuery是什么&#xff1f;二、JQuery的使用步骤1.引入2.书写位置3. 表示方法 三、JQuery选择器1.层级选择器2. 筛选选择器3. 排他思想4. 精品展示 四、jQuery样式操作1. 修改样式2.类操作1. 添加2. 移除3. 切换 五、jQuery动画1. 显示和隐藏2. 滑动1. slide2.…

Python 版本的 2024详细代码

2048游戏的Python实现 概述&#xff1a; 2048是一款流行的单人益智游戏&#xff0c;玩家通过滑动数字瓷砖来合并相同的数字&#xff0c;目标是合成2048这个数字。本文将介绍如何使用Python和Pygame库实现2048游戏的基本功能&#xff0c;包括游戏逻辑、界面绘制和用户交互。 主…

在Elasticsearch中,是怎么根据一个词找到对应的倒排索引的?

大家好&#xff0c;我是锋哥。今天分享关于【在Elasticsearch中&#xff0c;是怎么根据一个词找到对应的倒排索引的&#xff1f;】面试题。希望对大家有帮助&#xff1b; 在Elasticsearch中&#xff0c;是怎么根据一个词找到对应的倒排索引的&#xff1f; 在 Elasticsearch 中…

C# 数据结构之【图】C#图

1. 图的概念 图是一种重要的数据结构&#xff0c;用于表示节点&#xff08;顶点&#xff09;之间的关系。图由一组顶点和连接这些顶点的边组成。图可以是有向的&#xff08;边有方向&#xff09;或无向的&#xff08;边没有方向&#xff09;&#xff0c;可以是加权的&#xff…