Java设计模式---单例 工厂 代理模式

Java单例模式详解

一、引言

单例模式是设计模式中的一种,属于创建型模式。在软件工程中,单例模式确保一个类只有一个实例,并提供一个全局访问点。这种模式常用于那些需要频繁实例化然后引用,且创建新实例的开销较大的类,例如数据库连接池、缓存管理等。

二、单例模式定义

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

主要解决:一个全局使用的类频繁地创建与销毁所造成的资源浪费问题。

何时使用:当您想控制实例数目,节省系统资源的时候。

如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。

关键代码:构造函数是私有的。

三、Java实现单例模式的几种方式

  1. 懒汉式(线程不安全)
public class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

这种方式在多线程环境下不能保证单例,因为多个线程可能同时进入if条件判断内部,导致创建多个实例。

  1. 懒汉式(线程安全,同步方法)
public class Singleton {private static Singleton instance;private Singleton() {}public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

通过在getInstance方法上加synchronized关键字使其变为同步方法,解决了多线程环境下的安全性问题,但每次获取实例都要进行同步,性能损耗较大。

  1. 懒汉式(线程安全,双重检查锁定 - DCL,推荐使用)
public class Singleton {private volatile static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

双重检查锁定机制,首先判断实例是否存在,若不存在才进行同步处理,这样既保证了线程安全,又避免了每次都进行同步带来的性能损耗。

  1. 饿汉式(静态内部类)
public class Singleton {private Singleton() {}private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

静态内部类的方式在类加载时就完成了初始化,既保证了线程安全,也避免了同步带来的性能影响,同时也能保证单例对象的唯一性。

  1. 枚举式(最安全,推荐使用)
public enum Singleton {INSTANCE;public void whateverMethod() {// ...}
}

枚举类型的单例模式不仅能防止反射和反序列化的攻击,而且写法简单,易于理解,是实现单例的最佳选择。

四、注意事项

  • 单例模式虽然能节约系统资源,但也可能造成全局状态过多,增加系统的复杂度。
  • 对于可序列化类的单例模式,需要重写readResolve方法以防止反序列化时生成新的对象。

以上就是Java单例模式的详细解读,实际开发过程中应根据具体场景选择合适的实现方式。

Java工厂设计模式详解

一、引言

工厂模式是面向对象设计模式中的一种,主要用来解决对象创建的问题,封装了对象的创建过程,使客户端不需要知道具体的实现类就能创建所需的对象。根据抽象程度的不同,工厂模式分为简单工厂模式、工厂方法模式和抽象工厂模式。

二、工厂模式分类与定义

  1. 简单工厂模式(Simple Factory Pattern)

意图:提供一个用于创建对象的接口,让子类决定实例化哪一个类。

结构:由一个工厂类负责创建不同类的产品对象。

// 简单工厂角色
public class ShapeFactory {public Shape getShape(String type) {if ("CIRCLE".equals(type)) {return new Circle();} else if ("RECTANGLE".equals(type)) {return new Rectangle();} else if ("SQUARE".equals(type)) {return new Square();} else {throw new IllegalArgumentException("Invalid shape type");}}
}// 抽象产品角色
abstract class Shape {abstract void draw();
}// 具体产品角色
class Circle extends Shape {@Overridevoid draw() {System.out.println("Drawing a circle...");}
}// 其他具体产品类...
  1. 工厂方法模式(Factory Method Pattern)

意图:定义一个用于创建对象的接口,但让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。

结构:定义一个创建产品对象的接口,让子类决定生产什么产品。

// 抽象工厂角色
interface ShapeFactory {Shape createShape();
}// 具体工厂角色
class CircleFactory implements ShapeFactory {@OverrideShape createShape() {return new Circle();}
}// 其他具体工厂类...// 抽象产品角色
abstract class Shape {abstract void draw();
}// 具体产品角色
class Circle extends Shape {@Overridevoid draw() {System.out.println("Drawing a circle...");}
}// 其他具体产品类...
  1. 抽象工厂模式(Abstract Factory Pattern)

意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。

结构:提供一个接口,用于创建相关或相互依赖对象家族的一系列对象,而无需指定具体类。

// 抽象工厂角色
interface ColorFactory {Color getColor();
}interface ShapeFactory {Shape getShape();
}// 具体工厂角色
class RedColorFactory implements ColorFactory {@OverrideColor getColor() {return new RedColor();}
}class CircleShapeFactory implements ShapeFactory {@OverrideShape getShape() {return new Circle();}
}// 抽象产品角色
interface Color {void fill();
}interface Shape {void draw();
}// 具体产品角色
class RedColor implements Color {@Overridevoid fill() {System.out.println("Filling with red color...");}
}class Circle implements Shape {@Overridevoid draw() {System.out.println("Drawing a circle...");}
}// 其他具体产品类...

三、工厂模式优缺点

  • 优点

    • 将对象的创建和使用分离,使得系统耦合度降低。
    • 提高代码的可扩展性,增加新的产品类型时只需要添加新的工厂或产品类,不影响已有的代码。
  • 缺点

    • 当产品种类较多时,会导致类爆炸,因为每新增一种产品就需要新增对应的工厂类。
    • 违反开闭原则,如果需要新增一个产品,除了新增产品类外,可能还需要修改工厂类或抽象工厂类。

四、适用场景

  • 当一个类不知道它所必须创建的对象的确切类时。
  • 当一个类希望它的使用者指定它所创建的对象类型时。
  • 当类将职责委托给多个帮助子类中的某一个,并且用户希望可以动态地决定这个职责委托给哪个子类时。

通过上述介绍,您应该对Java中的工厂设计模式有了较为深入的理解。在实际开发中,可以根据需求选择合适的工厂模式来组织代码,提高程序的灵活性和可维护性。

Java代理设计模式详解

一、引言

代理设计模式(Proxy Design Pattern)是软件设计中常用的行为型设计模式之一,它为其他对象提供一个代理以控制对这个对象的访问。在Java编程中,代理模式的主要目的是为了在不改变原始目标类代码的基础上,通过引入一个额外的代理类来扩展或增强原有对象的功能。

1.1 定义

代理模式定义如下:
代理模式:给某个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式能够在客户端与目标对象之间增加一层间接层,从而实现对目标对象功能的增强、控制或者过滤。

1.2 模式结构

  • Subject(抽象主题): 定义了真实主题和代理主题的公共接口,这样代理可以作为真实主题的替代品。
  • RealSubject(真实主题): 实际完成工作的类,也是代理所代表的真实对象。
  • Proxy(代理): 保存一个对真实主题的引用,并且提供一个与真实主题相同的接口以便于在任何时候都可以将请求转发给真实主题处理;同时,在转发请求前或后执行附加操作。

1.3 应用场景

  • 访问控制:如权限验证,只有经过代理对象确认之后才能访问真实对象的方法。
  • 功能增强:例如在方法调用前后添加日志记录、事务管理等。
  • 虚拟代理:延迟加载,如图片预加载、数据库连接池中的连接对象创建等。
  • 远程代理:用于分布式系统中,代理对象负责与远程对象通信。
  • 缓存代理:缓存结果以提高性能,当请求数据时先检查代理是否有缓存的结果。
  • AOP(面向切面编程):Spring框架AOP模块底层就使用了动态代理技术。

二、Java中的代理实现方式

在Java中,代理主要分为两种类型:

2.1 静态代理

静态代理是在编译期间就已经确定代理类,代理类和被代理类的关系在代码中硬编码。

public interface Subject {void request();
}public class RealSubject implements Subject {@Overridepublic void request() {// 真实对象的实际业务逻辑}
}public class ProxySubject implements Subject {private RealSubject realSubject;public ProxySubject(RealSubject realSubject) {this.realSubject = realSubject;}@Overridepublic void request() {beforeRequest(); // 在调用实际方法前的操作realSubject.request();afterRequest(); // 在调用实际方法后的操作}private void beforeRequest() {// 添加前置逻辑,比如权限校验}private void afterRequest() {// 添加后置逻辑,比如日志记录}
}

2.2 动态代理

Java提供了动态生成代理类的技术,主要有两种实现机制:

2.2.1 JDK动态代理

JDK动态代理基于接口实现,通过java.lang.reflect.Proxy类和InvocationHandler接口。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class JdkProxy implements InvocationHandler {private Object target;public Object bind(Object target) {this.target = target;return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {beforeInvoke(method);Object result = method.invoke(target, args);afterInvoke(method);return result;}private void beforeInvoke(Method method) {// 前置处理}private void afterInvoke(Method method) {// 后置处理}
}// 使用示例
RealSubject realSubject = new RealSubject();
Subject proxy = (Subject) new JdkProxy().bind(realSubject);
proxy.request();
2.2.2 CGLIB代理

CGLIB库是一个强大的高性能代码生成库,可以在运行期扩展Java类与实现Java接口。它可以创建出一个被代理类的子类,因此不需要接口也能进行代理。CGLIB常用于Spring AOP框架中,对于没有实现接口的目标类也能提供代理支持。

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;public class CglibProxy implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {beforeInvoke(method);Object result = proxy.invokeSuper(obj, args);afterInvoke(method);return result;}private void beforeInvoke(Method method) {// 前置处理}private void afterInvoke(Method method) {// 后置处理}public Object createProxy(Class<?> clazz) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(clazz);enhancer.setCallback(this);return enhancer.create();}// 使用示例RealSubject realSubject = (RealSubject) new CglibProxy().createProxy(RealSubject.class);((Subject) realSubject).request();
}// 注意:这里假设RealSubject并未实现任何接口

三、总结

Java代理设计模式是一种重要的设计思想,它帮助开发者在不影响原始类的情况下,对类的行为进行扩展和控制。在实际开发中,无论是通过静态代理还是动态代理,都能在很多场合发挥重要作用,尤其是在框架设计、服务治理、性能优化以及AOP等领域得到广泛应用。学习并掌握代理模式有助于提升代码的灵活性和可维护性。

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

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

相关文章

Vue中$watch()方法和watch属性的区别

vue中$watch()和watch属性都是监听值的变化的&#xff0c;是同一个作用&#xff0c;但是有两个不同写法。 用法一&#xff1a; //注意&#xff1a;这种方法是监听不到对象的变化的。 this.$watch((newVal,oldVal)>{ }) 用法二&#xff1a; watch:{xxx:(newVal,oldVal)>…

NodeJS安装教程

1、 官网下载安装包 可以自己在官网下载 Node.Js中文网 https://nodejs.p2hp.com/ 2、安装步骤 1、双击安装包&#xff0c;一直点击下一步。 2、点击change按钮&#xff0c;更换到自己的指定安装位置&#xff0c;点击下一步&#xff08;不修改默认位置也是可以的 &#xf…

Simulink|光伏并网逆变器低电压穿越仿真模型

目录 主要内容 模型研究 1.模型总览 2.boost模块 3.Inverter模块 4.控制模块 5.信号模块 结果一览 下载链接 主要内容 该模型为光伏逆变器低电压穿越仿真模型&#xff0c;采用boost加NPC拓扑结构&#xff0c;基于MATLAB/Simulink建模仿真。模型具备中点平衡…

openai assistants api接入微信机器人,实现类GPTs功能

chatgpt网址:https://chat.xutongbao.top 比普通gpt多了代码解释器功能&#xff0c;和上传训练数据文件的功能&#xff0c;这两个功能就是GPTs拥有的&#xff0c;而普通gpt没有拥有的

Linux系统Shell脚本 ----- 编程规范和变量详细解读

一、Shell脚本概述 1、什么是Shell Linux系统中运行的一种特殊程序在用户和内核之间充当“翻译官”用户登录Linux系统时&#xff0c;自动加载一个Shell程序Bash是Linux系统中默认使用的Shell程序 2、Shell的作用 Linux系统中的shell是一个特殊的应用程序&#xff0c;它介于操…

商城系统中30分钟未付款自动取消订单怎么实现(简单几种方法)

实现以上功能 方法1&#xff1a;定时任务批量执行 写一个定时任务&#xff0c;每隔 30分钟执行一次&#xff0c;列出所有超出时间范围得订单id的列表 AsyncScheduled(cron "20 20 1 * * ?")public void cancelOrder(){log.info("【取消订单任务开始】"…

HTTP/1.1、HTTP/2、HTTP/3 基本概述

参考链接 https://xiaolincoding.com/network/2_http/http_interview.html#http-1-1-%E7%9B%B8%E6%AF%94-http-1-0-%E6%8F%90%E9%AB%98%E4%BA%86%E4%BB%80%E4%B9%88%E6%80%A7%E8%83%BD HTTP/1.1 HTTP/1.1 相比 HTTP/1.0 性能上的改进&#xff1a; 使用长连接的方式改善了 HTT…

Leetcode—25.K 个一组翻转链表【困难】

2023每日刷题&#xff08;八十二&#xff09; Leetcode—25.K 个一组翻转链表 算法思想 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val…

Conda python管理packages一 从入门到精通

Conda系列&#xff1a; 翻译: Anaconda 与 miniconda的区别Miniconda介绍以及安装Conda python运行的包和环境管理 入门Conda python管理环境environments 一 从入门到精通Conda python管理环境environments 二 从入门到精通Conda python管理环境environments 三 从入门到精通…

力扣每日一题 ---- 1970. 你能穿过矩阵的最后一天

这题对于没怎么做到过这题的朋友来说比较陌生&#xff0c;他给出的条件是两个都是动态的条件&#xff0c;一个条件随着另一个条件走&#xff0c;这个时候是很熟悉这题的朋友就会感觉比较麻烦&#xff0c;比较难&#xff0c;就不想写了&#xff0c;两个强相关条件的第一个是水每…

IT大侦“碳”:Concept Luna向循环设计持续演进

今天聊点轻松的话题。上个月&#xff0c;小编用来吃饭的家伙开始闹罢工&#xff0c;笔记本的触控和键盘突然没了反应&#xff0c;电脑虽然还能打开&#xff0c;但嗡嗡直叫的风扇让我意识到这件事并不简单。 你问我为什么电脑会出问题&#xff1f;好吧&#xff0c;那我得先搞清楚…

GBase 8s常见问题解析---追踪统计SQL执行情况 SQLTRACE

本文摘自GBASE南大通用社区&#xff0c;by&#xff1a;wty&#xff0c;原文请点击&#xff1a;GBase 8s常见问题 -- 追踪统计SQL执行情况 SQLTRACE|GBASE社区|天津南大通用数据技术股份有限公司|GBASE-致力于成为用户最信赖的数据库产品供应商 问题现象 某些SQL执行慢、有问题…

C# HSLCommunication与物联网技术结合的可能性及在智能制造中的应用

引言&#xff1a; 随着物联网&#xff08;IoT&#xff09;技术的迅速发展&#xff0c;智能制造和工业互联网等领域对高效、稳定的通信技术需求日益增长。C# HSLCommunication库作为一种高效的通信工具&#xff0c;与物联网技术的结合为这些领域带来了新的可能性。本文将详细介绍…

【Java万花筒】缓存与存储:Java应用中的数据处理利器

激发性能之源&#xff1a;深度剖析Java开发中的五大数据缓存与存储方案 前言 在现代软件开发中&#xff0c;高效地处理和存储数据是至关重要的任务。本文将介绍一系列在Java应用中广泛使用的数据缓存与存储库&#xff0c;涵盖了Ehcache、Redisson、Apache Cassandra、Hazelca…

js触发input的打开文件选择器,将本地图片回显以及上传

js触发input的打开文件选择器&#xff0c;将本地图片回显以及上传 你可以通过以下 JavaScript 代码触发文件选择器&#xff1a;这里的场景不是通过input标签来触达的文件选择器&#xff0c;这样对于样式较为复杂的上传可以在html结构上保持清爽愉快&#xff0c;不用多添加一个i…

java web mvc-08-Grails 入门介绍

拓展阅读 Spring Web MVC-00-重学 mvc mvc-01-Model-View-Controller 概览 web mvc-03-JFinal web mvc-04-Apache Wicket web mvc-05-JSF JavaServer Faces web mvc-06-play framework intro web mvc-07-Vaadin web mvc-08-Grails 开源 The jdbc pool for java.(java …

R语言【taxa】——is_*():检查对象是否为某个类

is_classification(x) 检查对象是否为 classification 类。 is_internode(x) 检查每个分类单元是否为节间。节间是指一个分类单元恰好有一个上级分类单元和 一个下级分类单元。这些分类群可以在不丢失它们之间的关系信息的情况下被移除。 x <- taxonomy(c(Carnivora, Felid…

设置Django中的静态文件

在Django中&#xff0c;静态文件&#xff08;如CSS、JavaScript、图片等&#xff09;是网站开发中不可或缺的一部分。为了让网站能够正确加载这些静态文件&#xff0c;我们需要在Django中进行相应的设置。 首先&#xff0c;我们需要在settings.py文件中设置STATIC_URL&#xf…

Unity通用渲染管线升级URP、HDRP

Unity通用渲染管线升级URP、HDRP 一、Build-in Pipline升级到 URP 一、Build-in Pipline升级到 URP 安装URP包 升级所有材质&#xff08;升级完成后材质会变成紫红色&#xff0c;Shader丢失&#xff0c;此为正常现象&#xff09; 创建 UniversalRenderPipelineAsset 配置文…

Pillow图像处理:从零开始的奇妙之旅

图像处理&#xff0c;就像是一场神奇的冒险&#xff0c;让我们的照片变得更有趣、更生动。而在这个冒险的旅途中&#xff0c;Pillow就如同一位魔法师&#xff0c;为我们开启了无尽的可能性。无论你是刚刚踏入图像处理领域的小白&#xff0c;还是已经略有基础的程序员&#xff0…