河北省建设工程网站/东莞网站优化公司哪家好
java设计模式
- java设计模式类型
- 常用设计模式
- 单例模式
- 单例模式的两种创建方式
- 饿汉式单例
- 懒汉式单例
- 工厂模式
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
- 原型模式
- 代理模式
- 代理模式结构
- 静态代理
- 动态代理
- jdk代理
- Cglib代理
java设计模式类型
根据完成的工作类型设计模式分为创建型模式、结构型模式和行为型模式。
创建型模式:是用来创建对象的模式,特点是将对象的创建和使用分离。有单例、原型、工厂方法、抽象工厂、建造者5中创建型模型
结构型创建模式:是用来将类或对象按某种布局组成更大的结构,有代理、桥接、组合等7种结构性模式
行为型模式:是用来将类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。。提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器 11 种行为型模式。
常用设计模式
单例模式
为了节省资源、保证数据内容的一致性,某些类只能创建一个实例,这就是单例模式
单例模式的特点:只有一个实例对象、该单例对象必须由单例类创建、单例类提供一个访问方法可以让外部类进行获取。
单例模式的两种创建方式
饿汉式单例
类一旦加载就会创建一个实例,不会存在线程安全问题
private static Demo demo=new Demo();private Demo(){}public Demo getInstance(){return demo;}
懒汉式单例
类加载时没有创建单例对象,只有第一次调用getInstance方法时才会去创建这个单例
private static Demo demo;private Demo(){}public Demo getInstance(){if(demo==null){demo=new Demo();}return demo;}
这种方式存在线程安全问题,当多个线程同时访问时,会出现创建多个对象的情况。
优化:
//这种方式虽然安全,但是效率低
public synchronized Demo getInstance(){if(demo==null){demo=new Demo();}return demo;}
//这种方式是线程安全的,效率也高,但是在执行过程中,可能会出现代码重排序的问题
public Demo getInstance(){//这里使用双重判断,第一个判断语句,是为了判断当线程进来时是demo是否被创建。if(demo==null){synchronized (Demo.class){//这个判断语句主要是判断对象未创建时第一次进来的请求进入时的判断。if(demo==null){demo=new Demo(); } } }return demo;}
//最终优化 使用volatile和双重检索
private static volatile Demo demo;public Demo getInstance(){if(demo==null){synchronized (Demo.class){if(demo==null){demo=new Demo();}}}return demo;}
Jdk 中的源码 Runtime 类就是一个单例类,利用 Runtime 类可以启动新的进程或进行相关运行时环境的操作。比如,取得内存空间以及释放垃圾空间。
工厂模式
工厂负责批量创建对象,使用对象时,只需要找到相对应的工厂
简单工厂模式
不符合开闭原则,适合长聘子类少的、创建操作简单的情况
该模式包含的角色:
工厂角色:负责创建所有实例的内部逻辑,提供静态方法,可以被外界调用,创建产品对象。
抽象产品角色:是所有对象的父类,可以时接口或抽象类
具体产品角色:是简单工厂模式的创建目标。
优点:实现的对象创建和调用的分离。
缺点:违背了开闭原则,产品子类过多会导致工厂类非常庞大,违背了高内聚原则‘
//汽车类 抽象产品角色
public interface Car {void run();}
//奥迪类 具体产品角色
public class Aodi implements Car{@Overridepublic void run() {System.out.println("奥迪汽车行驶");}
}
//宝马类 具体产品角色
public class Bmw implements Car{@Overridepublic void run() {System.out.println("宝马汽车行驶");}}
// 汽车工厂 工厂角色
public class CarFactory {public static Car createCar(String name){if(name.equals("aodi")){Aodi aodi = new Aodi();//aodi.return aodi;}if(name.equals("bmw")){return new Bmw();}return null;}
}
工厂方法模式
在简单工厂模式的基础上对工厂也进行了抽象,解决了违背开闭原则的问题
该模式中包含的角色及其职责.
抽象工厂角色:工厂方法模式的核心,与应用程序无关。任何在模式中创建的对
象的工厂类必须实现这个接口。
具体工厂角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关
的逻辑,并且受到应用程序调用以创建产品对象。
抽象产品角色:工厂方法模式所创建的对象的父类型,也就是产品对象的共同父
类或共同拥有的接口。
具体产品角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门
的具体工厂创建,它们之间往往——对应。
//抽象工厂类
public interface CarFactory {Car createCar();}
//具体工厂角色
public class AodiFactory implements CarFactory{@Overridepublic Car createCar() {return new AodiCar();}
}
public class BCFactroy implements CarFactory{@Overridepublic Car createCar() {return new BC();}}
//抽象产品角色
public interface Car {void run();
}
//具体产品角色
public class AodiCar implements Car{@Overridepublic void run() {System.out.println("奥迪汽车行驶");}
}
public class BC implements Car{@Overridepublic void run() {System.out.println("奔驰");}
}
抽象工厂模式
抽象工厂模式中,一个具体的工厂负责创建一系列相互关联的产品。
//抽象工厂类
public interface AbstractFactory {Car getCar();Phone getPhone();}
//具体工厂角色
public class AodiFactory implements AbstractFactory{@Overridepublic Car getCar() {return new AodiCar();}@Overridepublic Phone getPhone() {return new AodiPhone();}
}
//抽象产品角色
public interface Phone {void call();
}
public interface Car {void run();
}
//具体产品角色
public class AodiCar implements Car{@Overridepublic void run() {System.out.println("奥迪汽车行驶");}
}
public class AodiPhone implements Phone{@Overridepublic void call() {System.out.println("奥迪手机打电话");}
}
优点:获取具体系列产品只需要通过具体系列工厂获取,无序关心创建的细节。
原型模式
原型模式是指创建一个对象,并且通过这个对象作为原型来创建新的对象,相当于复制多个具有相同信息的对象。
实现方式:使用对象克隆的方式创建新的对象。
代理模式
代理模式就是给对象提供一个代理,通过代理对象来对原对象进行控制。是的客户不能直接和对象进行交互,只能通过代理对象来进行操作。
案例:买火车票不一定要去火车站买,可以通过 12306 网站或者去火车票代售点
优点:保护目标对象、代理对象可以扩展目标对象的功能,代理模式将客户端与目标分离,降低系统的耦合度。
代理模式结构
1.抽象主题类:使用接口和抽象类声明真实主题类和代理对象的业务方法
2.真实主题类:实现抽象主题中的业务,是目标对象是最终要引用的对象。
3.代理类:提供与真实主题相同的结构,引用了真实主题,它可以访问、控制和扩展真实主题的功能
1.png)]
代理分为两种:动态代理和静态代理
静态代理
静态代理的特点。代理类接受一个抽象主题接口,实现任何该接口的对象,都可以通过代理类进行代理。
优点:可以对目标对象进行功能扩展
缺点:一个代理类只能代理一个接口,必须现有接口再有代理,接口发生改变,代理类也要修改
以买票为例
//抽象主题 买票
public interface Ticket {void buy();
}
//真实主题 目标对象类
public class TrainTicket implements Ticket {@Overridepublic void buy() {System.out.println("买火车票");}
}
public class PlaneTicket implements Ticket {@Overridepublic void buy() {System.out.println("买飞机票");}
}
//代理类
public class MeiTuan implements Point {Ticket ticket;public MeiTuan(Ticket ticket) {this.ticket= ticket;}@Overridepublic void buy() {System.out.println("添加额外功能");ticket.buy();}
}
//测试类
public class Test {public static void main(String[] args) {//具体对象Ticket trainTicket = new TrainTicket();Ticket planeTicket = new PlaneTicket();//创建用户代理对象Ticket ticket = new Ticket(trainTicket);ticket.buy();Ticket ticket1 = new Ticket(planeTicket);ticket1.buy();}
}
动态代理
在动态代理中不需要手动的创建类,只需要编写一个动态的处理器,代理对象在运行时动态的来创建。
动态代理分为jdk动态代理和cglid动态代理
jdk代理
jdk动态代理是通过反射来实现的,借助java自带的java.lang.reflect.Proxy生成。
实现步骤:
1.编写一个委托类的接口
2.实现一个委托类
3.创建一个动态代理类,实现现 InvocationHandler 接口,并重写该 invoke
方法。
4.在测试类中,生成动态代理的对象。
实现步骤的前两步和静态代理没有区别。
/*动态代理类代理类不需要实现与目标类相同的接口,这样就可以代理任意的目标类但是是有要求的,目标类必需实现接口,此种方式是动态代理的实现方式之一: jdk代理 是一种纯反射机制实现(动态获取目标类接口方法)*/
public class DynamicProxy implements InvocationHandler {Object object;//真实对象,接收任何的目标类对象public DynamicProxy(Object object) {this.object = object;}/*在代理类中调用目标类中的具体方法,动态的将代理动态对象,目标类中要调用的方法,及方法中的参数传递过来Method method 就是动态获取的真正要执行的方法*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("之前开启事务");method.invoke(object);System.out.println("之后提交事务");return proxy;}//真正意义上,运行时生成代理对象的方法public Object getProxy(){return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);}}
//测试类
public class Test {public static void main(String[] args) {TrainTicket trainTicket = new TrainTicket();DynamicProxy dtproxy = new DynamicProxy(trainTicket);//自己创建的代理类对象//这才是真正的创建动态代理对象Ticket ticket = (Train)dtproxy.getProxy();userDao.saveUser();//使用代理对象调用接口中的方法,获取当前调用的方法,最终调用invoke方法}
}
jdk动态代理,减少了对接口业务的依赖,降低了耦合度,但是jdk动态代理有一个缺点就是他必须要创建一个代理接口。
Cglib代理
Cglib代理解决了jdk动态代理的缺点。CGLIB(Code Generator Library)是一个强大的、高性能的代码生成库。CGLib 采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
Cglib 子类代理实现方法:
1.需要引入 cglib 的 jar 文件,但是 Spring 的核心包中已经包括了 Cglib 功能,所以直接引入 spring-core-xxx.jar 即可
2.引入功能包后,就可以在内存中动态构建子类
3.代理的类不能为 final,否则报错
4.目标对象的方法如果为 final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
CGLIB 创建的动态代理对象比JDK 创建的动态代理对象的性能更高,但是 CGLIB创建代理对象时所花费的时间却比 JDK 多得多。所以对于单例的对象,因为无需频繁创建对象,用 CGLIB 合适,反之使用 JDK 方式要更为合适一些。同时由于 CGLib 由于是采用动态创建子类的方法,对于 final 修饰的方法无法进行代理。
/** 动态代理类*/
public class CGLibProxy implements MethodInterceptor {private Enhancer enhancer = new Enhancer();public Object getProxy(Class<?> clazz){ enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } /** 拦截所有目标类方法的调用 * 参数: * obj 目标实例对象 * method 目标方法的反射对象 * args 方法的参数 * proxy 代理类的实例 */ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {//代理类调用父类的方法 System.out.println("开始事务"); Object obj1 = proxy.invokeSuper(obj, args); System.out.println("关闭事务"); return obj1; }
}
//具体主题
public class UserDaoImpl{public void save() {System.out.println("UserDaoImpl:save()");}
}
//测试类
public class Test {public static void main(String[] args) {CGLibProxy proxy = new CGLibProxy(); UserDaoImpl userDaoImpl = (UserDaoImpl) proxy.getProxy(UserDaoImpl.class);userDaoImpl.save();}
}
相关文章:

java常用设计模式
java设计模式java设计模式类型常用设计模式单例模式单例模式的两种创建方式饿汉式单例懒汉式单例工厂模式简单工厂模式工厂方法模式抽象工厂模式原型模式代理模式代理模式结构静态代理动态代理jdk代理Cglib代理java设计模式类型 根据完成的工作类型设计模式分为创建型模式、结…...

死锁(5.1)
死锁 1 死锁的基本概念 1.1 死锁的定义 死锁是发生在一组相互合作或竞争的线程或进程中的一个问题。因此可以定义为:一组竞争系统资源或相互通信的进程相互的“永久”阻塞。若无外力作用,这组进程将永远不能继续执行。 1.2死锁产生的原因进程 &…...

Python 之 Matplotlib 第一个绘图程序和基本方法
文章目录一、第一个 Matplotlib 绘图程序1. Matplotlib 绘图的基本步骤二、Matplotlib 的基本方法1. 图表名称 plt.title()2. x 轴和 y 轴名称3. 设置 x 轴和 y 轴的刻度4. 显示图表 show()5. 图例 legend()6. 图例的图例位置设置7. 显示每条数据的值 x,y 值的位置一、第一个 M…...

数据结构与算法(一):概述
数据结构学了有一年左右的时间了,但是一直没有详细地总结一下,现在回想起来,感觉有些内容忘记了。所以接下来一段时间我将重新归纳总结一下,算是温故而知新了。 一、数据结构 1、定义 数据结构是计算机存储、组织数据的方式。在…...

Spring3之Bean的属性详解
简介 Spring 中大量使用到 Bean 的注入来实现各个模块之间的依赖,本章将详细介绍 Bean 的主要属性 id 和 name 属性 每个 Bean 可以有一个 id 属性,并可以根据该 id 在 IoC 容器中查找该 Bean,该 id 属性值必须在IoC 容器中唯一 可以不指定…...

C语言之结构体内存的计算
结构体的内存 一.提出疑问 结构体占用的是一片连续的内存空间,大小是由成员变量的类型决定的。但并不是计算所有成员变量的类型大小之和那么简单。 先举一个实例: struct student {int age; //4个字节int telephone; //4个字节 }; int main() {struc…...

Java网络编程之UDP和TCP套接字
文章目录一. 网络编程概述二. UDP网络编程1. UDP套接字2. UDP客户端回显服务器程序2.1 UDP回显服务器2.2 UDP客户端2.3 UDP实现查词典的服务器三. TCP网络编程1. TCP套接字2. TCP客户端回显服务器程序2.1 TCP回显服务器2.2 TCP客户端2.3 解决服务器无法同时出力多个客户端的问题…...

Linux进程信号产生以及捕捉
一.什么是信号 生活中,有哪些信号相关的场景呢,比如:红绿灯,闹钟,转向灯等等 1.这里我们要知道,你为什么认识这些信号呢,记住了对应场景下的信号+后续是有”动作“要你执行的 2.我们…...

11. GLSL(OpenGL Shader Language)常用知识点汇总
1. 说明: 在使用OPenGL进行三维模型渲染时,需要使用到两个着色器对模型进行位置设置和颜色设置,分别为顶点着色器和片段着色器,这两个着色器是使用 GLSL 语法进行编写的。这篇文章总结了一些GLSL中的一些基本语法知识。 2. 基本…...

转发一张网络工程师考试的试卷2021.5.15
网络工程师考试 单选题 (30题,每题1分,共30分) 1. 你在一个网络中实现DHCP服务,配置一些计算机成为DHCP客户端,由于工作需要,一台系统为Windows 10 的客户端要把从DHCP服务器获得的地址释放&a…...

AMD发布23.2.1 新驱动 支持开年新作《魔咒之地》
如果说2023年有什么新作,《魔咒之地(Forspoken)》当属开年大作之一,1月25日才在steam平台发售。虽然开售后的表现似乎不如想象中优秀,加之价格相对昂贵,令不少玩家望而却步,但如果只是想尝鲜&am…...

开放平台如何做接口的签名和加解密?
目录安全性功能介绍实现流程开放平台依赖代码AES加解密工具类PlatformConfigRequestUtilsPlatformServiceCommonCodeZuulFilterHelperServerResponsePlatformContactRsaSignatureRsaUtilsStreamUtil开放平台-解密过滤器开放平台-加密过滤器调用方代码公共代码Get-DemoPost-Demo…...

Mr. Cappuccino的第40杯咖啡——Kubernetes之Pod生命周期
Kubernetes之Pod生命周期Pod生命周期官方文档Pod的状态初始化容器案例钩子函数Exec命令TCPSocketHTTPGet案例容器探测Exec命令TCPSocketHTTPGet探测时间重启策略Pod生命周期官方文档 Pod生命周期官方文档 Pod的状态 pending:挂起,apiserver创建了pod资…...

记一次OOM
1,问题描述: 新上了一版代码之后,上游服务请求我们服务失败,报错:“服务不可用”,发现注册中心上服务掉线,查询日志:发现oom:Java heap space,GC overhead limit exceeded。 容易…...

idea插件生成dao类service类controller类以及mapper.xml
idea插件生成dao类service类controller类以及mapper.xml 安装插件Easycode和MybatisX,不用自己写代码 1.Files——》Settings——》Plugins,分别搜索Easycode和MybatisX,点击下载。 2.新建一个springboot模板,选择的依赖如下 3.…...

DML 数据操作语言
概述 DML英文全称是Data Manipulation Language(数据操作语言),用来对数据库中表的数据记录进行增、删、改操作。 添加数据(INSERT)修改数据(UPDATE)删除数据(DELETE) 添加数据 1、给指定字段…...

PySpark实战一之入门
1、PySpark的编程模型 分三个模块: 数据输入:通过SparkContext对象,完成数据输入 数据处理计算:输入数据后得到RDD对象,对RDD对象的成员方法进行迭代计算 数据输出:最后通过RDD对象的成员方法࿰…...

【DockerCE】Docker-CE 23.0.1正式版发布
很意外啊!Docker社区版竟然直接从20.xx.xx版本,升级到23.xx.xx版本了。官网地址(For RHEL/CentOS 7.9):https://download.docker.com/linux/centos/7/x86_64/stable/Packages/23.0.1版本官方安装包如下:# l…...

vscode开发的Vue家用电器维修服务系统nodejs+mysql
主要功能包括管理员:首页、个人中心、用户管理、维修员管理、维修信息管理、维修申请管理、维修处理管理、家电类别管理、配件信息管理、配件领用管理、维修结果管理、家电维修知识管理、公告信息管理、留言板管理,用户:首页、个人中心、维修…...

PyQt5数据库开发1 4.2 配置SQL Server 2008 数据源(ODBC编程)
文章目录 配置SQL Server 2008 数据源(ODBC编程) 1. 了解要配置的数据源服务器名称,以及数据库和对应表 2. 打开控制面板,点击管理工具 3. 双击数据源 4. 选择“用户DSN”选项卡,点击“添加” 5. 选择SQL Serv…...

【JavaEE】多线程代码实例:单例模式与阻塞队列BlockingQueue
目录 单例模式: 什么是单例模式? 单例模式的实现方式: 饿汉模式: 懒汉模式: 基于并发编程对单例模式线程安全问题的讨论: 阻塞队列: 标准库中的阻塞队列: 自实现阻塞…...

算法思想 - 搜索算法
本文主要介绍算法中搜索算法的思想,主要包含BFS,DFS。搜索相关题目深度优先搜索和广度优先搜索广泛运用于树和图中,但是它们的应用远远不止如此。BFS广度优先搜索的搜索过程有点像一层一层地进行遍历,每层遍历都以上一层遍历的结果…...

C#底层库--日期扩展类(上周、本周、明年、前年等)
系列文章 C#底层库–记录日志帮助类 本文链接:https://blog.csdn.net/youcheng_ge/article/details/124187709 C#底层库–数据库访问帮助类(MySQL版) 本文链接:https://blog.csdn.net/youcheng_ge/article/details/126886379 …...

如何在 Webpack 中开启图片压缩
工具对比 npmtrends.com/image-minim… 这四个压缩工具,从下载量来看,image-webpack-loader 较多,image-minimizer-webpack-plugin、imagemin-webpack-plugin 次之,imagemin-webpack 已经不再维护,因此不考虑此工具。 …...

Web-Filter
## 今日内容 1. Filter:过滤器 2. Listener:监听器 # Filter:过滤器 1. 概念: * 生活中的过滤器:净水器,空气净化器,土匪、 * web中的过滤器:当访问服务器的资源时…...

测试写文章自动保存
近日恰逢双十一,瞅了瞅自己干瘪的钱包,没忍心入手期待已久的 macPro,只好在虚拟机里玩一下 mac好了,等以后钱包傲气的时候再来个真实的。 安装环境: windows10 VMWare14.2 2018-7-28 小嘚瑟补充:唧唧歪歪大半年,一夜回到解放前,终于剁手整了个真机,可以折腾一下了 ——…...

云平台搭建实例
嗨嗨,每天一更是不是很奈斯?我也觉得,昨天晚上我学校的老师借一天一千的设备,只能用七天,所以我拿出来给你们没有设备和刚用设备的看看吧。操作:首先我们将云平台安装好后,插上网线,…...

【Airplay_BCT】关于Bonjour的概念解答
1.什么是Bonjour? Bonjour,也称为零配置网络,可以自动发现 IP 网络上的计算机、设备和服务。 Bonjour 使用行业标准 IP 协议,允许设备自动发现彼此,无需输入 IP 地址或配置 DNS 服务器。具体来说,Bonjour …...

C++深入浅出(九)—— 多态
文章目录1. 多态的概念2. 多态的定义及实现🍑 多态的构成条件🍑 虚函数🍑 虚函数的重写🍑 虚函数重写的两个例外🍑 C11的override 和 final🍑 重载、覆盖(重写)、隐藏(重定义)的对比3. 抽象类🍑…...

shell学习4
目录 一、统计文本中的词频 二、压缩javascript 三、打印文件的或行中的第n个单词或列---awk 3.1 利用awk打印文件中每行中的第五个单词。 3.2 利用awk打印当前目录下的文件的权限和文件名 3.3 利用awk打印从M行到N行这个范围内的所有文本 3.4 利用awk 部分提取文件中的内…...