项目中使用的设计模式

项目中使用的设计模式

  • 请列举几个项目中常用的设计模式
  • 什么是设计模式,在项目中使用了那些设计模式
    • 动态代理模式
      • JDK动态代理
      • CGLIB动态代理
    • 单例模式
      • 懒汉式(非线程安全)
      • 饿汉式
      • 懒汉式(线程安全)
    • 工厂模式
    • 观察者模式
    • 装饰器模式

请列举几个项目中常用的设计模式

    单例模式(Singleton pattern)用于Runtime,Calendar和其他的一些类中。工厂模式(Factory pattern)被用于各种不可变的类如 Boolean,像Boolean.valueOf,观察者模式(Observer pattern)被用于 Swing 和很多的事件监听中。装饰器设计模式(Decorator design pattern)被用于多个 Java IO 类中。

什么是设计模式,在项目中使用了那些设计模式

    设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。设计模式是代码可用性的延伸

    设计模式分类:创建型模式结构型模式行为型模式

动态代理模式

    代理模式分为静态代理与动态代理,静态代理不做过多解释(项目中不常用),动态代理分为JDK动态代理CGLIB动态代理,Spring2.x之前使用的代理模式为JDK动态代理,但仍需要定义接口才能实现功能,有一定的局限性,因此在Spring2.x之后,采用了CGLIB动态代理技术。

JDK动态代理

/*** 接口*/
public interface Target {public String  execute();
}
/*** 实现类*/
public class TargetImpl implements Target {@Overridepublic String execute() {System.out.println("Target execute");return "execute";}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;/*** 代理类*/
public class DynamicProxyHandler implements InvocationHandler {private Target target;public DynamicProxyHandler(Target target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("======before======");Object result = method.invoke(target, args);System.out.println("======after======");return result;}
}
import java.lang.reflect.Proxy;/*** 测试类*/
public class DynamicProxyTest {public static void main(String[] args) {Target target = new TargetImpl();DynamicProxyHandler handler = new DynamicProxyHandler(target);Target proxy = (Target) Proxy.newProxyInstance(TargetImpl.class.getClassLoader(), TargetImpl.class.getInterfaces(), handler);String result = proxy.execute();System.out.println(result);}
}

输出结果为

======before======
Target execute
======after======
execute

CGLIB动态代理

    CGLib采用了非常底层的字节码技术,也就是ASM 字节码操作框架,在运行时动态生成被代理类的子类字节码。该子类重写了父类(被代理类)的所有飞final方法。因此CGLIB的局限性也在于此,被代理类不能继承其他类或被final修饰的类。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。

/*** 目标类*/
public class Target {public String execute() {String message = "======test======";System.out.println(message);return message;}
}
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** 通用代理类*/
public class MyMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("======MethodInterceptor start======");// 使用invokeSuper而不是invoke,避免无限递归Object result = methodProxy.invokeSuper(o, objects);System.out.println("======MethodInterceptor end======");return result;}
}
import net.sf.cglib.proxy.Enhancer;/*** 测试类*/
public class CgLibTest {public static void main(String[] args) {System.out.println("***************");CgLibTest test = new CgLibTest();Target proxyTarget = (Target) test.createProxy(Target.class);String res = proxyTarget.execute();System.out.println(res);}public Object createProxy(Class targetClass) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(targetClass);enhancer.setCallback(new MyMethodInterceptor());return enhancer.create();}
}

输出结果为

***************
======MethodInterceptor start======
======test======
======MethodInterceptor end======
======test======

代理类的对象生成过程由Enhancer类实现,大概步骤如下:

  1. 生成代理类Class的二进制字节码;
  2. 通过Class。forName加载二进制字节码,生成Class对象;
  3. 通过反射机制获取实例构造,并初始代理类对象。

单例模式

    单例模式是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。主要解决:一个全局使用的类频繁的创建与销毁。单利模式主要分为懒汉饿汉,他俩的区别在于创建对象的时机,一个是当你调用类的getInstance()方法时,才会初始化对象,而另一个在类初始化时,就会创建对象,他俩只会创建同一个对象。

懒汉式(非线程安全)

public class Singleton {private static Singleton instance;// 私有化构造方法private Singleton() {}// 提供一个对象,全局仅创建一次public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

饿汉式

public class Singleton {private static Singleton instance = new Singleton();// 私有化构造方法private Singleton() {}public static Singleton getInstance() {return instance;}
}

懒汉式(线程安全)

public class Singleton {// 确保可见性与有序性private static volatile Singleton instance = null;// 构造方法私有化private Singleton() {}// 双重校验锁 + volatilepublic static Singleton getInstance(){if (instance == null) {synchronized (Singleton.class) {// 避免CPU切换到另一个线程创建对象,创建完再切换回来if (instance == null) {instance = new Singleton();}}}return instance;}
}

工厂模式

    工厂模式是Java中最场景的设计模式之一。这种类型的设计模式属于创建者模式,它提供了一种创建对象的最佳方式。意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。主要解决:主要解决接口选择的问题。
建一个 Shape 接口和实现 Shape 接口的实体类,然后定义工厂类 ShapeFactory。用 ShapeFactory 来获取 Shape 对象。它将向 ShapeFactory 传递信息,以便获取它所需对象的类型。
步骤1:创建一个接口
Shapa.java

public interface Shape {void draw();
}

步骤2:创建实现接口的实体类Rectangle.java、

public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Inside Rectangle::draw() method");}
}

Square.java

public class Square implements Shape{@Overridepublic void draw() {System.out.println("Inside Square::draw() method.");}
}

Circle.java

public class Circle implements Shape {@Overridepublic void draw() {System.out.println("Inside Circle::draw() method.");}
}

步骤3:创建一个工厂,生成基于给定信息的实体类对象。
ShapeFactory.java

public class ShapeFactory {// 使用getShape() 方法获取形状类型的对象public Shape getShape(String shapeType) {if (shapeType == null) {return null;}shapeType = shapeType.toLowerCase(Locale.ROOT);switch (shapeType){case "circle":return new Circle();case "rectangle":return new Rectangle();case "square":return new Square();default: return null;}}
}

步骤4:使用该工厂,通过传递类型信息来获取实体类的对象。
FactoryPatternDemo.java

public class FactoryPatternDemo {public static void main(String[] args) {ShapeFactory shapeFactory = new ShapeFactory();// 获取Circle对象,并调用它的draw方法Shape shape1 = shapeFactory.getShape("CIRCLE");shape1.draw();// 获取Rectangle对象,并调用它的draw方法Shape shape2 = shapeFactory.getShape("RECTANGLE");shape2.draw();// 获取Square对象,并调用它的draw方法Shape shape3 = shapeFactory.getShape("SQUARE");shape3.draw();}
}

步骤5:验证输出结果

Inside Circle::draw() method.
Inside Rectangle::draw() method
Inside Square::draw() method.

观察者模式

    观察者模式属于行为模式。当对象间存在一对多的关系时,则使用观察者模式。比如,当一个对象被修改时,则会自动通知它的依赖对象。意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用性和低耦合,保证高度的协作。

    实现:观察者模式使用三个类Subject、Observer和Client。Subject对象带有绑定观察者到Client对象和从Client对象解绑观察者的方法。
在这里插入图片描述
步骤1:创建Subject类
Subject.java

public class Subject {private List<Observer> observers = new ArrayList<>();private int state;public int getState() {return state;}public void setState(int state){this.state = state;notifyAllObservers();}public void attach(Observer observer) {observers.add(observer);}public void notifyAllObservers() {for(Observer observer : observers) {observer.update();}}
}

步骤2:创建Observer类
Observer.java

public abstract class Observer {protected Subject subject;public abstract void update();
}

步骤3:创建实体观察者类:
BinaryObserver.java

public class BinaryObserver extends Observer{public BinaryObserver(Subject subject){this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {System.out.println("Binary String" + Integer.toBinaryString(subject.getState()));}
}

OctalObserver.java

public class OctalObserver extends Observer{public OctalObserver(Subject subject){this.subject = subject; this.subject.attach(this);}@Overridepublic void update() {System.out.println("Octal String: " + Integer.toOctalString(subject.getState()));}
}

HexaObserver.java

public class HexaObserver extends Observer{public HexaObserver(Subject subject){this.subject = subject; this.subject.attach(this);}@Overridepublic void update() {System.out.println("Hex String: " + Integer.toHexString(subject.getState()).toUpperCase());}
}

步骤4:使用SUbject和实体类观察者对象
ObserverPatternDemo.java

public class ObserverPatternDemo {public static void main(String[] args) {Subject subject = new Subject();new BinaryObserver(subject);new OctalObserver(subject);new HexaObserver(subject);System.out.println("First state change: 15");subject.setState(15);System.out.println("------------");System.out.println("Second state change: 10");subject.setState(10);}
}

步骤5:验证结果

First state change: 15
Binary String: 1111
Octal String: 17
Hex String: F
------------
Second state change: 10
Binary String: 1010
Octal String: 12
Hex String: A

装饰器模式

    装饰器模式允许向一个现有的对象添加新功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的一个类包装。意图:动态代给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。主要解决:一般的,我们为了拓展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。

    实现:我们将创建一个Shape接口和实现Shape接口的实体类。然后我们创建一个实现了Shape接口的抽象装饰类ShapeDecorator,并且把Shape对象作为它的实例变量。
RedShapeDecorator是实现了ShapeDecorator的实体类;
DecoratorPatternDemo是我们的演示类使用RedShapeDecorator来装饰Shape对象。
在这里插入图片描述
步骤1:创建一个接口:
Shape.java

public interface Shape {void draw();
}

步骤2:创建实现接口的实体类
Rectangle.java

public class Rectangle implements Shape{@Overridepublic void draw() {System.out.println("Shape: Rectangle");}
}

Circle.java

public class Circle implements Shape{@Overridepublic void draw() {System.out.println("Shape Circle");}
}

步骤3:创建实现了Shape接口的抽象装饰类
ShapeDecorator.java

public abstract class ShapeDecorator implements Shape{protected Shape decoratorShape;public ShapeDecorator(Shape decoratorShape){this.decoratorShape = decoratorShape;}@Overridepublic void draw(){decoratorShape.draw();}
}

步骤4:创建扩展了ShapeDecorator类的实体装饰类
RedShapeDecorator.java

public class RedShapeDecorator extends ShapeDecorator{public RedShapeDecorator(Shape decoratorShape) {super(decoratorShape);}@Overridepublic void draw(){decoratorShape.draw();setRedBorder(decoratorShape);}private void setRedBorder(Shape decoratorShape){System.out.println("Border Color: Red");}
}

步骤5:使用RedShape来装饰Shape对象
DecoratorPatternDemo.java

public class DecoratorPatternDemo {public static void main(String[] args) {Shape circle = new Circle();Shape redCircle = new RedShapeDecorator(new Circle());Shape redRectangle = new RedShapeDecorator(new Rectangle());System.out.println("Circle with normal border");circle.draw();System.out.println("\nCircle of red border");redCircle.draw();System.out.println("\nRectangle of red border");redRectangle.draw();}
}

步骤6:验证结果

Circle with normal border
Shape CircleCircle of red border
Shape Circle
Border Color: RedRectangle of red border
Shape: Rectangle
Border Color: Red

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

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

相关文章

实战教程:从“对象文件为空“到仓库重生——修复 Git 仓库损坏全记录

文章目录实战教程&#xff1a;从"对象文件为空"到仓库重生——修复 Git 仓库损坏全记录案发现场&#xff1a;一个严重损坏的仓库修复之旅&#xff1a;四步让仓库重获新生准备工作&#xff1a;创建安全备份第 1 步&#xff1a;清理战场——删除所有空对象第 2 步&…

ansible 操作家族(ansible_os_family)信息

1. 操作系统系列 &#xff08;ansible_os_family&#xff09;ansible web -m setup -a filteransible_os_family2. 操作系统家族为 RedHat 时执行任务--- - hosts: websrvsremote_user: roottasks:- name: Install package on RedHat systemsyum:name: httpdstate: presentwhen…

一文学会c++继承 组合

文章目录继承简介定义访问限定符和继承方式⭐基类派生类赋值转换继承的作用域派生类的默认成员函数继承与友元继承与静态成员⭐复杂的菱形继承虚拟继承组合继承简介 继承是面向对象程序设计代码复用的重要手段&#xff0c;使得程序员可以在保持原类的基础上扩展&#xff0c;新…

.Net下载共享文件夹中的文件

由于IIS站点权限等问题&#xff0c;总是没找到处理办法&#xff0c;所以改用外挂的winform的方式来下载共享文件&#xff08;也可以改为使用windows服务的方式&#xff09;。 前提需要先在资源管理器中登录到共享文件夹&#xff0c;确保系统能访问。 服务端代码 (.NET后端) usi…

目标检测数据集 - 眼睛瞳孔检测数据集下载「包含COCO、YOLO两种格式」

数据集介绍&#xff1a;眼睛瞳孔检测数据集&#xff0c;真实采集高质量人脸眼部图片数据&#xff0c;适用于人脸定位、人脸疾病如白内障等疾病的视觉检测。数据标注标签包括 eyepupil 瞳孔一 个缺陷类别&#xff1b;适用实际项目应用&#xff1a;眼睛瞳孔检测项目&#xff0c;以…

Keil MDK-ARM V5.42a 完整安装教程

文章目录一、安装前期准备二、Keil MDK-ARM 主程序安装三、器件支持包&#xff08;Pack&#xff09;安装四、许可证激活五、安装验证Keil MDK&#xff08;Microcontroller Development Kit&#xff09;是针对 Arm Cortex-M 系列微控制器的专业开发环境&#xff0c;集成了 μVis…

WPF中引用其他元素各种方法

在WPF中&#xff0c;引用其他元素的方式有多种&#xff0c;每种方式适用于不同场景&#xff0c;各有优缺点。除了x:Reference&#xff0c;常用的还有以下几种&#xff1a; 一、ElementName 绑定&#xff08;最常用的XAML绑定方式&#xff09; 通过元素的x:Name属性引用同一作用…

Python生成统计学公式

一元线性回归模型 2.1回归分析概述/25 一、回归分析基本概念/25 二、总体回归函数/27 三、随机误差项/29 四、样本回归函数/30 2.2 一元线性回归模型的参数估计/32 一、参数估计的普通最小二乘法/32 二、拟合优度/35 2.3基本假设与普通最小二乘估计量的统计性质/36 一、一元线性…

网络工程师--华为命令专题

一、交换机 交换机分类&#xff1a;1.根据交换方式划分&#xff1a;&#xff08;1&#xff09;存储转发式交换&#xff08;Store and Forward&#xff09;&#xff08;2&#xff09;直通式交换&#xff08;Cut-through&#xff09;&#xff08;3&#xff09;碎片过滤式交换&…

判断可编辑div的光标是否在最前面

要判断一个可编辑div(contenteditable)中的光标是否位于最前面&#xff0c;可以使用以下几种方法&#xff1a; 方法一&#xff1a;使用Selection和Range API function isCaretAtStart(div) {const selection window.getSelection();if (selection.rangeCount 0) return false…

【unity实战】使用Unity程序化生成3D随机地牢(附项目源码)

最终效果 文章目录最终效果前言1、理解程序生成的核心概念2、种子值的核心作用3、程序生成的实际应用4、主流程序生成技术概览5、选择合适的技术实战1、素材2、生成一面墙变换矩阵数据3、渲染墙壁4、加点随机不同的墙壁效果5、绘制四面墙壁4、在四个角落生成支柱5、生成地板6、…

多账号管理方案:解析一款免Root的App分身工具

之前有小伙伴问阿灿有没有可以软件分身的免费软件&#xff0c;后来阿灿找到了一款可以无限分身的app感觉很实用&#xff0c;只有10M大小 02软件介绍说白了它能给各种app和游戏做分身&#xff0c;包括V信、qQ、某音、某付宝这些&#xff0c;而且支持最新的安卓15系统。每个分身…

(附源码)基于PHP和Vue的网上购物平台

内容摘要 内容摘要: 随着互联网技术的迅猛发展&#xff0c;网上购物已成为人们日常生活的重要组成部分。本文围绕PHPVue技术栈构建的网上购物平台展开研究&#xff0c;深入探讨了该平台的架构设计与实现细节。平台前端采用Vue框架&#xff0c;利用其组件化开发和数据驱动的特性…

51单片机

中断系统1.什么是中断当CPU正在处理某件事的时候外界发生了紧急事件请求&#xff0c;要求CPU暂停当前的工作&#xff0c;转而去处理这个紧急事件&#xff0c;处理完以后&#xff0c;再回到原来被中断的地方&#xff0c;继续原来的工作&#xff0c;这样的过程称为中断2.为什么要…

前端开发:HTML(5)—— 表单

下面我们来学习表单。 目录 什么是Web表单&#xff1f; 表单标签 1.form标签 2.输入框 文本框和密码框 单选框和复选框 1.单选框 2.复选框 3.按钮 &#xff08;1&#xff09;普通按钮 &#xff08;2&#xff09;提交按钮 &#xff08;3&#xff09;重置按钮 &#…

【YOLOv8改进 - C2f融合】C2f融合SFS-Conv(空间 - 频率选择卷积)提升特征多样性,同时减少参数和计算量

YOLOv8目标检测创新改进与实战案例专栏 专栏目录: YOLOv8有效改进系列及项目实战目录 包含卷积,主干 注意力,检测头等创新机制 以及 各种目标检测分割项目实战案例 专栏链接: YOLOv8基础解析+创新改进+实战案例 文章目录 YOLOv8目标检测创新改进与实战案例专栏 介绍 摘要 文…

如何将照片从POCO手机传输到Mac电脑

将照片从POCO手机传输到Mac电脑可能会有些困难&#xff0c;因为与iPhone不同&#xff0c;POCO设备没有原生的macOS支持。这常常让用户寻找简单、有效的方法来移动图片&#xff0c;同时避免丢失质量&#xff0c;节省时间&#xff0c;并避免复杂的软件设置。如果你想知道如何将照…

最新教程 | CentOS 7 内网环境 Nginx + ECharts 页面离线部署手册(RPM 安装方式)

&#x1f4c1; 一、准备阶段&#xff08;在联网电脑上完成&#xff09; 1.1 下载 Nginx 官方 RPM 安装包 在联网电脑浏览器中访问 Nginx 官方稳定版本仓库&#xff1a; &#x1f517; 地址&#xff1a;http://nginx.org/packages/centos/7/x86_64/ ☁️云盘&#xff1a;htt…

Redis 常用数据类型 (下)

文章目录前言一 Hash 哈希1. Hash 相关命令hset 和 hgethexistshdelhkeyshvalshgetallhmgethlenhsetnxhincrbyincrbyfloat2. Hash 命令小结3. Hash 内部编码Hash 在缓存中的应用场景介绍缓存方式对比二、List 列表1. LIST总体介绍2. List 普通命令lpushlpushxrpushrpushxlrange…

Java Lambda表达式:简洁高效的函数式编程

1 lambda表达式Lambda 表达式本质是一个匿名函数&#xff0c;用于把函数作为参数&#xff0c;传入方法中&#xff0c;实现函数式编程风格。使用Lambda 表达式可以使代码变的更加简洁紧凑。语法格式&#xff1a;(parameters)-> expression 或 (parameters)->{ statements…