JAVA设计模式详解(独家AI解析)

news2024/12/24 2:00:23

JAVA设计模式详解(独家AI解析)

  • 一、JAVA介绍
  • 二、JAVA设计模式六大原则
  • 三、JAVA设计模式介绍
  • 四、JAVA设计模式详解
    • 4.1 单例模式
      • 4.1.1 懒汉式(Lazy Initialization)
      • 4.1.2 饿汉式(Lazy Initialization)
    • 4.2 代理模式
      • 4.2.1 静态代理
      • 4.2.2 动态代理
    • 4.3 策略模式

一、JAVA介绍

可以查阅JAVA快速入门体验

在这里插入图片描述

二、JAVA设计模式六大原则

在这里插入图片描述

设计模式的六大原则是一组指导性原则,它们帮助开发人员设计出灵活、可维护和可扩展的软件系统。以下是这些原则的简要介绍:

  1. 单一职责原则(Single Responsibility Principle,SRP):
    一个类应该只有一个引起它变化的原因。换句话说,一个类应该只有一个职责。这样可以提高类的内聚性,使其更容易理解、修改和测试。
  2. 里氏替换原则(Liskov Substitution Principle,LSP):
    所有使用父类引用的地方,都应该能够使用子类对象进行替换,而不会导致程序逻辑错误。子类应该保持父类的行为规范,遵循里氏替换原则可以提高系统的可靠性和可扩展性。
  3. 依赖倒置原则(Dependency Inversion Principle,DIP):
    高层模块不应该依赖于低层模块,二者都应该依赖于抽象。抽象不应该依赖于具体实现细节,具体实现细节应该依赖于抽象。通过依赖注入和面向接口编程等方式,可以实现依赖倒置原则。
  4. 接口隔离原则(Interface Segregation Principle,ISP):
    客户端不应该强迫依赖于它们不需要的接口。应该将大而全的接口拆分成小而精确的接口,以避免类依赖无用的接口方法。
  5. 迪米特法则(Law of Demeter,LoD):
    一个对象应该对其他对象有尽可能少的了解,只与直接的朋友通信。不要和陌生人说话。迪米特法则减少了对象之间的耦合,使系统更加灵活、可维护和可扩展。
  6. 开闭原则(Open-Closed Principle,OCP):
    软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。通过使用抽象、接口和多态等特性,可以使系统在不修改现有代码的情况下进行扩展。

这些原则共同为软件设计提供了指导,帮助开发人员构建高质量、可维护的系统。请注意,这些原则并非硬性规定,而是在实践中的经验总结,根据具体情况进行灵活应用。

三、JAVA设计模式介绍

在这里插入图片描述

Java中常用的设计模式有23种,这些模式是根据软件设计中常见的问题和解决方案而被提出的。以下是这些设计模式的分类和简要介绍:

  1. 创建型模式(Creational Patterns):
    • 单例模式(Singleton Pattern)
    • 工厂方法模式(Factory Method Pattern)
    • 抽象工厂模式(Abstract Factory Pattern)
    • 建造者模式(Builder Pattern)
    • 原型模式(Prototype Pattern)
  2. 结构型模式(Structural Patterns):
    • 适配器模式(Adapter Pattern)
    • 桥接模式(Bridge Pattern)
    • 组合模式(Composite Pattern)
    • 装饰器模式(Decorator Pattern)
    • 外观模式(Facade Pattern)
    • 享元模式(Flyweight Pattern)
    • 代理模式(Proxy Pattern)
  3. 行为型模式(Behavioral Patterns):
    • 责任链模式(Chain of Responsibility Pattern)
    • 命令模式(Command Pattern)
    • 解释器模式(Interpreter Pattern)
    • 迭代器模式(Iterator Pattern)
    • 中介者模式(Mediator Pattern)
    • 备忘录模式(Memento Pattern)
    • 观察者模式(Observer Pattern)
    • 状态模式(State Pattern)
    • 策略模式(Strategy Pattern)
    • 模板方法模式(Template Method Pattern)
    • 访问者模式(Visitor Pattern)

这些设计模式提供了在软件开发过程中常见问题的解决方案,并且可以帮助提高代码的可维护性、灵活性和复用性。在实际开发中,根据具体的需求和情况选择合适的设计模式是很重要的。

四、JAVA设计模式详解

主要对单例、代理和策略模式进行详解。

4.1 单例模式

在这里插入图片描述

单例模式是一种创建型设计模式,用于确保一个类只有一个实例,并提供一个全局访问点来获取该实例。它常用于需要共享资源或控制某些唯一资源的情况下。

单例模式的实现方式有多种,以下是其中两种常见的方式。

4.1.1 懒汉式(Lazy Initialization)

在首次调用获取实例的方法时才创建实例。如果实例已经存在,则直接返回该实例。这种方式延迟了实例的创建,但在多线程环境下需要注意线程安全。

示例代码如下:

public class Singleton {
    private static Singleton instance;

    private Singleton() {
        // 私有构造函数,防止外部实例化
    }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

4.1.2 饿汉式(Lazy Initialization)

饿汉式(Eager Initialization): 在类加载时就创建实例,确保实例的唯一性。这种方式简单直接,但可能会造成资源浪费,因为实例在整个程序生命周期中都存在。

示例代码如下:

public class Singleton {
    private static final Singleton instance = new Singleton();

    private Singleton() {
        // 私有构造函数,防止外部实例化
    }

    public static Singleton getInstance() {
        return instance;
    }
}

以上代码中,通过将构造函数设为私有,防止外部直接实例化Singleton类。getInstance()方法提供了全局访问点,返回Singleton类的唯一实例。

使用示例:

public class Main {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        // 使用singleton对象进行操作
    }
}

通过调用Singleton.getInstance()方法获取Singleton类的实例,然后可以使用该实例进行相应的操作。

需要注意的是,单例模式并不适用于所有场景,因为它引入了全局状态和共享资源,可能会增加代码的复杂性和耦合度。在使用单例模式时,需要权衡其优缺点,并根据具体需求进行选择。

4.2 代理模式

在这里插入图片描述

代理模式是一种结构型设计模式,它允许通过创建一个代理对象来控制对另一个对象的访问。代理对象充当了客户端和目标对象之间的中介,可以在访问目标对象时添加额外的功能或控制。

代理模式的实现方式有多种,以下是其中两种常见的方式。

4.2.1 静态代理

在编译时就已经确定代理类和目标类的关系,即代理类是通过手动编码创建的。静态代理需要为每个目标类编写一个代理类,这样会导致代码冗余。

示例代码如下(Java):

// 目标接口
public interface Image {
    void display();
}

// 目标类
public class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk();
    }

    private void loadFromDisk() {
        System.out.println("Loading image: " + filename);
    }

    public void display() {
        System.out.println("Displaying image: " + filename);
    }
}

// 代理类
public class ImageProxy implements Image {
    private RealImage realImage;
    private String filename;

    public ImageProxy(String filename) {
        this.filename = filename;
    }

    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename);
        }
        realImage.display();
    }
}

在上述示例中,Image 接口定义了目标类和代理类的共同行为,RealImage 是目标类,负责加载和显示图像。ImageProxy 是代理类,用于控制对 RealImage 的访问。当调用 display() 方法时,代理类会首先判断目标对象是否已经创建,若未创建则创建目标对象,然后调用目标对象的 display() 方法。

使用示例(Java):

public class Main {
    public static void main(String[] args) {
        Image image = new ImageProxy("image.jpg");
        image.display();
    }
}

4.2.2 动态代理

在运行时动态生成代理类,无需手动编写代理类。通过使用 Java 提供的 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来实现动态代理。

示例代码如下(Java):

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 目标接口
public interface Image {
    void display();
}

// 目标类
public class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk();
    }

    private void loadFromDisk() {
        System.out.println("Loading image: " + filename);
    }

    public void display() {
        System.out.println("Displaying image: " + filename);
    }
}

// InvocationHandler 实现类
public class ImageInvocationHandler implements InvocationHandler {
    private Object target;

    public ImageInvocationHandler(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method: " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("After method: " + method.getName());
        return result;
    }
}

// 使用动态代理创建代理对象
public class ProxyFactory {
    public static Object createProxy(Object target) {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new ImageInvocationHandler(target)
        );
    }
}

在上述示例中,Image 接口和 RealImage 类与静态代理示例中相同。ImageInvocationHandler 类是实现 InvocationHandler 接口的代理处理器类,用于在调用目标方法前后添加额外的逻辑。ProxyFactory 类用于创建动态代理对象。

使用示例(Java):

public class Main {
    public static void main(String[] args) {
        Image realImage = new RealImage("image.jpg");
        Image imageProxy = (Image) ProxyFactory.createProxy(realImage);
        imageProxy.display();
    }
}

在上述示例中,通过调用 ProxyFactory.createProxy() 方法创建了一个代理对象 imageProxy,并将其转换为 Image 接口类型。当调用代理对象的 display() 方法时,代理处理器会先执行自定义的逻辑,然后再调用目标对象的 display() 方法。

需要注意的是,代理模式可以提供额外的功能,例如延迟加载、权限控制、日志记录等。通过代理对象,可以在不修改目标对象的前提下,对其进行控制和增强。

4.3 策略模式

在这里插入图片描述

策略模式是一种行为型设计模式,它允许在运行时选择算法的行为。该模式将算法封装成独立的策略类,并使这些策略类可以相互替换,从而使得算法的变化独立于使用算法的客户端。

策略模式由三个主要角色组成:

  1. 环境(Context):环境类持有一个策略对象,并在需要时调用策略对象的方法。
  2. 抽象策略(Strategy):抽象策略定义了策略对象的接口,所有具体策略类都必须实现该接口。
  3. 具体策略(Concrete Strategy):具体策略类实现了抽象策略定义的接口,提供了具体的算法实现。

下面是一个示例代码,以展示策略模式的实现方式(Java):

// 抽象策略接口
public interface SortingStrategy {
    void sort(int[] array);
}

// 具体策略类 - 冒泡排序
public class BubbleSortStrategy implements SortingStrategy {
    public void sort(int[] array) {
        System.out.println("Sorting array using Bubble Sort");
        // 冒泡排序的具体实现
    }
}

// 具体策略类 - 快速排序
public class QuickSortStrategy implements SortingStrategy {
    public void sort(int[] array) {
        System.out.println("Sorting array using Quick Sort");
        // 快速排序的具体实现
    }
}

// 环境类
public class SortManager {
    private SortingStrategy sortingStrategy;

    public void setSortingStrategy(SortingStrategy sortingStrategy) {
        this.sortingStrategy = sortingStrategy;
    }

    public void sortArray(int[] array) {
        if (sortingStrategy != null) {
            sortingStrategy.sort(array);
        }
    }
}

在上述示例中,SortingStrategy 是抽象策略接口,定义了排序算法的方法 sort()。BubbleSortStrategy 和 QuickSortStrategy 是具体策略类,分别实现了冒泡排序和快速排序算法。

SortManager 是环境类,它持有一个策略对象,并在需要时调用策略对象的 sort() 方法来进行排序操作。

使用示例(Java):

public class Main {
    public static void main(String[] args) {
        int[] array = {5, 2, 8, 3, 1};

        SortManager sortManager = new SortManager();

        // 使用冒泡排序策略
        sortManager.setSortingStrategy(new BubbleSortStrategy());
        sortManager.sortArray(array);

        // 使用快速排序策略
        sortManager.setSortingStrategy(new QuickSortStrategy());
        sortManager.sortArray(array);
    }
}

在上述示例中,首先创建了一个整型数组 array,然后通过创建 SortManager 对象来进行排序操作。通过调用 setSortingStrategy() 方法,可以在运行时设置不同的排序策略,然后调用 sortArray() 方法进行排序。

策略模式的优点是可以灵活地替换算法,使得算法的变化独立于使用算法的客户端。此外,策略模式还可以避免使用大量的条件语句来选择不同的算法,提高了代码的可读性和可维护性。

至此,JAVA设计模式全解(独家AI解析)分享完成,后续会陆续输出更多JAVA相关的篇章;查阅过程中若遇到问题欢迎留言或私信交流。

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

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

相关文章

本地化ddddocr库,完成验证码图片识别,完整流程

1.pycharm-3.8环境,代码,ddddocr库,以及测试图片 2.代码: import ddddocr ocr ddddocr.DdddOcr(oldTrue) with open("1.jpg", rb) as f:image f.read() res ocr.classification(image) print(res)3.完整打包&#…

sheng的学习笔记-【中】【吴恩达课后测验】Course 3 - 结构化机器学习项目 - 第二周测验

课程3_第2周_测验题 目录:目录 要解决的问题 ① 为了帮助你练习机器学习的策略,本周我们将介绍另一个场景,并询问你将如何行动。 ② 我们认为这个在机器学习项目中工作的“模拟器”将给出一个任务,即领导一个机器学习项目可能…

教师必备宝藏,强烈推荐

亲爱的教师朋友们,你们是不是在为学期末成绩查询而头疼呢?一学期下来,成堆的试卷和成绩单,还有学生家长的各种咨询,让人应接不暇。现在,我给你们分享一个教师必备的宝藏,让你们的成绩查询工作变…

Mac虚拟机哪个好用,CrossOver23.6虚拟机激活许可证激活码2023最新分享

刚买了苹果电脑的用户,经常会因为用不惯苹果系统而想换Windows系统,实际上也的确是,许多流行游戏或软件都暂不支持Mac系统,可行的办法是安装Mac虚拟机或是双系统,以供支持在苹果电脑上使用Windows应用。下面本文就来讲…

小程序如何设置自取规则

​在小程序中,自取规则是指当客户下单时选择无需配送的情况下,如何设置相关的计费方式、指定时段费用、免费金额、预定时间和起取金额。下面将详细介绍如何设置这些规则,以便更好地满足客户的需求。 在小程序管理员后台->配送设置->自…

JavaScript进阶 第二天笔记

JavaScript 进阶 - 第2天 了解面向对象编程的基础概念及构造函数的作用,体会 JavaScript 一切皆对象的语言特征,掌握常见的对象属性和方法的使用。 了解面向对象编程中的一般概念能够基于构造函数创建对象理解 JavaScript 中一切皆对象的语言特征理解引用…

Vue中的加密方式(js-base64、crypto-js、jsencrypt、bcryptjs)

目录 1.安装js-base64库 2. 在Vue组件中引入js-base64库 3.使用js-base64库进行加密 4.Vue中其他加密方式 1.crypto-js 2.jsencrypt 3.bcryptjs 1.安装js-base64库 npm install js-base64 --save-dev 2. 在Vue组件中引入js-base64库 import { Base64 } from js-ba…

springboot操作nosql的mongodb,或者是如何在mongodb官网创建服务器并进行操作

第一步:在mongodb的官网里面创建云服务器 点进去 这是免费的,由于是一个项目只可以创建一个,这里我已经创建好了 用本地的mongodb服务也是可以的 第二步:点击connect,下载连接mongodb的软件:MongoDBCompass 第三步&am…

钉钉小程序生态6—钉钉OA自定义审批流的创建和使用

文章导航 钉钉小程序生态1—区分企业内部应用、第三方企业应用、第三方个人应用 钉钉小程序生态2—区分小程序和H5微应用 钉钉小程序生态3—钉钉扫码登录PC端网站 钉钉小程序生态4—钉钉小程序三方企业应用事件与回调 钉钉小程序生态5—钉钉群机器人消息通知和钉钉工作通知 钉…

【嵌入式开发学习】__单片机中容易造成内存泄露的几个痛点

目录 前言 一、程序运行 二、什么是内存泄露? 三、内存泄露的严重后果! 四、如何定位到泄露的要点? 五、三大痛点 1. 访问越界 2. 栈 3. 堆 六、泄露常见的场景 1. 重新赋值 2. 首先释放父块 3. 返回值的不正确处理 七、常见的…

无监督学习-K-means

1、 什么是无监督学习 一家广告平台需要根据相似的人口学特征和购买习惯将美国人口分成不同的小组,以便广告客户可以通过有关联的广告接触到他们的目标客户。Airbnb 需要将自己的房屋清单分组成不同的社区,以便用户能更轻松地查阅这些清单。一个数据科学…

账号运营的底层逻辑---获客思维

什么是运营? 运营是做什么的? 什么是内容运营? 什么是活动运营? 一篇带你搞清楚所有的底层逻辑!

三、W5100S/W5500+RP2040树莓派Pico<TCP Client数据回环测试>

文章目录 1. 前言2. 协议简介2.1 简述2.2 优点2.3 应用 3. WIZnet以太网芯片4. TCP Client数据回环测试4.1 程序流程图4.2 测试准备4.3 连接方式4.4 相关代码4.5 测试现象 5. 注意事项6. 相关链接 1. 前言 在当今的计算机网络环境中,TCP(传输控制协议&am…

整理指定文件夹下的所有文件,以类树状图显示并生成对应超链接

最近在整理家里学习资料的时候,由于年代久远,找不到我想要找的文件,windows文件搜索速度感觉太慢。于是想要生成一份类似文件索引的东西来显示所有资料,让我可以快速的找到需要的资料路径 直接上代码 import os import datetim…

基于Java的医院远程预约管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding) 代码参考数据库参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

2、Linux权限理解

个人主页:Lei宝啊 愿所有美好如期而遇 目录 前言 Linux权限的概念 1.文件访问者的分(人) 2.文件类型和访问权限(事物属性) 3.文件权限值的表示方法 4.文件访问权限的相关设置方法 file指令 目录的权限 粘滞位 关于权限的总结 前言 在开始Linux权限理…

IDEA: 自用主题及字体搭配推荐

文章目录 1. 字体设置推荐2. 主题推荐3. Rainbow Brackets(彩虹括号)4. 设置背景图片 下面是我的 IDEA 主题和字体,它们的搭配效果如下: 1. 字体设置推荐 在使用 IntelliJ IDEA 进行编码和开发时,一个合适的字体设置可以提高你的工作效率和舒…

Python---for循环中的两大关键字break和continue

之前在while循环中,也是用到两个关键字。 相关链接: 所以,在循环结构中都存在两个关键字:break和continue break:主要功能是终止整个循环 break:代表终止整个循环结构 continue:代表中止当…

【Note】二叉树的遍历

二叉树的遍历 二叉树的基本结构:根节点(Data)、左子树(LChild)和右子树(RChild)。 因此只要依次遍历这三部分,就遍历了整个二叉树。 如果用L、D、R分别表示遍历左子树、访问根结点…

不用编程超简单的自动化测试工具:Airtest入门篇教程!

目录 一、背景 二、什么是Airtest 三、Airtest下载安装 四、Airtest入门使用教程 4.1 连接设备: 4.2 具体测试场景案例: 五、总结 一、背景 很多刚入行或从其他行业转行做测试的同学,日复一日每天做点工已经点得疲惫和麻木&#xff0…