Java设计模式的常见应用场景 java设计模式及应用案例
yuyutoo 2024-10-12 01:31 5 浏览 0 评论
一、Java I/O中的设计模式
1、适配器模式
适配器模式就是把一个类的接口变换成客户端所能接受的另一种接口,从而使两个接口不匹配而无法在一起工作的两个类能够在一起工作。通常被用在一个项目需要引用一些开源框架来一起工作时,这些框架的内部都有一些关于环境信息的接口,需要从外部引入,但是外部的接口不一定能匹配,在这种情况下,就需要适配器模式来转换接口。
Java的I/O类库中有许多这样的需求,如将字符串转成字节数据保存到文件中,将字节数据变成数据流等。具体来说,InputStreamReader和OutputStreamWriter就是适配器的体现。InputStreamReader实现了Reader接口,并且持有InputStream的引用,其作用是将InputStream适配到Reader。源角色就是InputStream代表的实例对象,目标角色就是Reader类。OutputStreamWriter也是类似的方式。
2、装饰器模式
装饰器的作用是使得被装饰者功能更强大,而且装饰前后的使用方式不变。Java I/O类库中有许多不同的功能组合情况,这些不同的功能组合都是使用装饰器模式实现的。以FileInputStream为例,其类结构如下:
由于java I/O库需要很多性能的各种组合,如果这些性能都是用继承来实现,那么每一种组合都需要一个类,这样就会造成大量行重复的类出现。如果采用装饰模式,那么类的数目就会大大减少,性能的重复也可以减至最少。因此装饰模式是java I/O库基本模式。装饰模式的引进,造成灵活性和复杂性的提高。因此在使用 java I/O 库时,必须理解java I/O库是由一些基本的原始流处理器和围绕它们的装饰流处理器所组成的。
InputStream类是以抽象组件的形式存在,而FileInputStream就是具体组件,它实现了抽象接口的所有方法,并且持有InputStream对象的引用。FileInputStream就是一个装饰类,而BufferInputStream是这个装饰类的具体实现者,它给InputStream加入了新的功能,使得InputStream读取的数据保存在内存中,从而提高读取性能。
3、适配模式和装饰模式的区别
适配模式是为了处理两个借口不一致,改变现有接口使其匹配。
装饰模式是在不改变现有接口的前提下,加入新的功能。
二、Javac中的访问者模式
javac 是java语言编程编译器。全称javacompilation。javac工具读由java语言编写的类和接口的定义,并将它们编译成字节代码的class文件。javac 可以隐式编译一些没有在命令行中提及的源文件。用 -verbose 选项可跟踪自动编译。当编译源文件时,编译器常常需要它还没有识别出的类型的有关信息。对于源文件中使用、扩展或实现的每个类或接口,编译器都需要其类型信息。这包括在源文件中没有明确提及、但通过继承提供信息的类和接口。
Javac的编译过程涉及许多语法分析,所有就有语法分析器、语义分析器和代码生成器,期间需要多次遍历语法树。然而每次遍历语法树都会进行不同的处理动作,这是如何实现的呢?就是通过采用访问者模式设计的,每次遍历都是一次访问者的执行过程。
访问者模式可以使数据结构和对数据结构的操作解耦,使得增加对数据结构的操作不需要去修改数据结构,也不必去修改原有的操作,从而执行时再定义新的Visitor实现者就行了。在Javac中不同的编译阶段都定义了不同的访问者模式实现。
三、Tomcat中的设计模式
1、门面模式
Tomcat中门面设计模式使用得很多,因为Tomcat中有很多组件,每个组件要相互交互数据,用门面设计模式隔离数据是个很好的方法。
可以看到,HttpRequestFacade类封装了HttpRequest接口,能够提供数据,通过HttpRequestFacade访问到的数据被代理到HttpReauest中、通常被封装的对象都被设为Private或者Protectd的,防止在Facade中直接访问。
2、观察者模式
Tomcat中观察者模式也有多处使用,前面讲的控制组件生命周期的Lifecycle就是这 种模式的体现,还有对Servlet实例的创建、Session的管理、Container等都是同样的原理。 下面主要看一下Lifecycle的具体实现。
Lifecycle的观察者模式结构图如图所示。
在上面的结构图中,LifecycleListener代表的是抽象观察者,它定义一个lifecycleEvent 方法,这个方法就是当主题变化时要执行的方法。ServerLifecycleListener代表的是具体的 观察者,它实现了 LifecycleListener接口的方法,就是这个具体的观察者具体的实现方式。 Lifecycle接口代表的是抽象主题,它定义了管理观察者的方法和它所要做的其他方法。而 StandardServer代表的是具体主题,它实现了抽象主题的所有方法。这里Tomcat对观察者 做了扩展,谓加了另外两个类:LifecycleSupport和LifecycleEvent,它们作为辅助类扩展 了观察者的功能。LifecycleEvent使得可以定义事件类别,不同的事件可区别处理,更加灵活。LifecycleSupport类代理了主题对多观察者的管理,将这个管理抽出来统一实现,以 后如采修改只要修改LifecycleSupport类就可以了,不需要去修改所有的具体主题,因为 所有具体主题对观察者的操作都被代理给LifecycleSupport类了。这可以认为是观察者模式的改进版。
3、命令设计模式
Tomcat中命令模式在Connector和Container组件之间有体现,Tomcat作为一个应用 服务器,无疑会接收到很多请求,如何分配和执行这些请求是必须的功能。
下面分析一下Tomcat是如何实现命令模式的,下图是Tomcat命令模式的结构图。
Connector作为抽象请求者,HttpConnector作为具体请求者。HttpProcessor作为命令。 Container作为命令的抽象接受者,ContainerBase作为具体的接受者。客户端就是应用服务器Server组件了。Server首先创建命令请求者HttpConnector对象,然后创建命令 HttpProcessor对象。再把命令对象交给命令接受者ContainerBase容器来处理,命令最终是被Tomcat的Container执行的。命令可以以队列的方式进来,Container也可以以不同的 方式来处理请求,如HTTP1.0协议和HTTP1.1的处理方式就不同。
4、责任链模式
Tomcat 中一个最容易发现的设计模式就是责任链设计模式,这个设计模式也是 Tomcat 中 Containe设计的基础,整个容器就是通过一个链连接在一起的,这个链一直将请求正确地传递给最终处理请求的那个 Servlet 。在Tomcat中这种设计模式儿乎被完整地使用,Tomcat的容器设置就是责任链模式,从Engine到Host再到Cortex,一直到Wrapper都通过这个链传递请求。
四、Spring中的设计模式
1、简单工厂模式
又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一。
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。
spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得bean对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。如下配置,就是在 HelloItxxz 类中创建一个 itxxzBean。
<beans>
<bean id="singletonBean" class="com.kang.HelloItxxz">
<constructor-arg>
<value>Hello! 这是singletonBean!value>
</constructor-arg>
</ bean>
<bean id="itxxzBean" class="com.kang.HelloItxxz"
singleton="false">
<constructor-arg>
<value>Hello! 这是itxxzBean! value>
</constructor-arg>
</bean>
</beans>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
2、工厂方法模式
通常由应用程序直接使用new创建新的对象,为了将对象的创建和使用相分离,采用工厂模式,即应用程序将对象的创建及初始化职责交给工厂对象。
一般情况下,应用程序有自己的工厂对象来创建bean.如果将应用程序自己的工厂对象交给Spring管理,那么Spring管理的就不是普通的bean,而是工厂Bean。
以工厂方法中的静态方法为例讲解一下:
import java.util.Random;
public class StaticFactoryBean {
public static Integer createRandom() {
return new Integer(new Random().nextInt());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
建一个config.xm配置文件,将其纳入Spring容器来管理,需要通过factory-method指定静态方法名称,createRandom方法必须是static的,才能找到
<bean id="random"
class="example.chapter3.StaticFactoryBean" factory-method="createRandom" scope="prototype"
/>
- 1
- 2
- 3
3、单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
spring中的单例模式完成了后半句话,即提供了全局的访问点BeanFactory。但没有从构造器级别去控制单例,这是因为spring管理的是是任意的java对象。 Spring下默认的bean均为singleton,可以通过singleton=“true|false” 或者 scope=“?”来指定
4、代理模式
在Spring的Aop中,使用的Advice(通知)来增强被代理类的功能。Spring实现这一AOP功能的原理就使用代理模式(1、JDK动态代理。2、CGLib字节码生成技术代理。)对类进行方法级别的切面增强,即,生成被代理类的代理类, 并在代理类的方法前,设置拦截器,通过执行拦截器重的内容增强了代理方法的功能,实现的面向切面编程。
5、模板方法模式
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
Template Method模式一般是需要继承的。这里想要探讨另一种对Template Method的理解。spring中的JdbcTemplate,在用这个类时并不想去继承这个类,因为这个类的方法太多,但是我们还是想用到JdbcTemplate已有的稳定的、公用的数据库连接,那么我们怎么办呢?我们可以把变化的东西抽出来作为一个参数传入JdbcTemplate的方法中。但是变化的东西是一段代码,而且这段代码会用到JdbcTemplate中的变量。怎么办?那我们就用回调对象吧。在这个回调对象中定义一个操纵JdbcTemplate中变量的方法,我们去实现这个方法,就把变化的东西集中到这里了。然后我们再传入这个回调对象到JdbcTemplate,从而完成了调用。这可能是Template Method不需要继承的另一种实现方式吧。
6、策略模式
Spring中的策略模式使用多如牛毛,所谓策略模式就是定义了算法族,分别封装起来,让他们之前可以互相转换,此模式然该算法的变化独立于使用算法的客户。Spring的事务管理机制就是典型的策略模式,Spring事务策略是通过PlatformTransactionManager接口实现的,它是整个Spring事务的核心。它是对事务策略的一个高度抽象,不依赖于任何具体的事务策略,而对于底层的具体的事务策略它相应的有不同的实现类。而对于不同的事务策略的切换通常由Spring容器来负责管理,应用程序既无须与具体的事务API耦合,也无须与特定的实现类耦合而将应用和持久化技术,事务API彻底分离开来。
五、SpringMVC中的模板模式
所谓模板模式就是定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。SpringMVC在保证整个框架流程稳定的情况下,预留很多口子,而这些口子都是所谓的模板方法,可以自由指定,从而保证了灵活性,接下来的很多使用最佳实践都是基于这种设计模式才可以实现。例如,下面的代码中doResolveException(..)就是一个口子,子类方法doResolveException(..)可以定义具体如何处理异常。
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
if (shouldApplyTo(request, handler)) {
logException(ex, request);
prepareResponse(ex, response);
return doResolveException(request, response, handler, ex);
} else {
return null;
}
}
protected abstract ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex);
- 上一篇:未关闭的文件流会引起内存泄露么?
- 下一篇:java转换流 java流转字符串
相关推荐
- Mysql和Oracle实现序列自增(oracle创建序列的sql)
-
Mysql和Oracle实现序列自增/*ORACLE设置自增序列oracle本身不支持如mysql的AUTO_INCREMENT自增方式,我们可以用序列加触发器的形式实现,假如有一个表T_WORKM...
- 关于Oracle数据库12c 新特性总结(oracle数据库19c与12c)
-
概述今天主要简单介绍一下Oracle12c的一些新特性,仅供参考。参考:http://docs.oracle.com/database/121/NEWFT/chapter12102.htm#NEWFT...
- MySQL CREATE TABLE 简单设计模板交流
-
推荐用MySQL8.0(2018/4/19发布,开发者说同比5.7快2倍)或同类型以上版本....
- mysql学习9:创建数据库(mysql5.5创建数据库)
-
前言:我也是在学习过程中,不对的地方请谅解showdatabases;#查看数据库表createdatabasename...
- MySQL面试题-CREATE TABLE AS 与CREATE TABLE LIKE的区别
-
执行"CREATETABLE新表ASSELECT*FROM原表;"后,新表与原表的字段一致,但主键、索引不会复制到新表,会把原表的表记录复制到新表。...
- Nike Dunk High Volt 和 Bright Spruce 预计将于 12 月推出
-
在街上看到的PandaDunk的超载可能让一些球鞋迷们望而却步,但Dunk的浪潮仍然强劲,看不到尽头。我们看到的很多版本都是为女性和儿童制作的,这种新配色为后者引入了一种令人耳目一新的新选择,而...
- 美国多功能舰载雷达及美国海军舰载多功能雷达系统技术介绍
-
多功能雷达AN/SPY-1的特性和技术能力,该雷达已经在美国海军服役了30多年,其修改-AN/SPY-1A、AN/SPY-1B(V)、AN/SPY-1D、AN/SPY-1D(V),以及雷神...
- 汽车音响怎么玩,安装技术知识(汽车音响怎么玩,安装技术知识视频)
-
全面分析汽车音响使用或安装技术常识一:主机是大多数人最熟习的音响器材,有关主机的各种性能及规格,也是耳熟能详的事,以下是一些在使用或安装时,比较需要注意的事项:LOUDNESS:几年前的主机,此按...
- 【推荐】ProAc Response系列扬声器逐个看
-
有考牌(公认好声音)扬声器之称ProAcTablette小音箱,相信不少音响发烧友都曾经,或者现在依然持有,正当大家逐渐掌握Tablette的摆位设定与器材配搭之后,下一步就会考虑升级至表现更全...
- #本站首晒# 漂洋过海来看你 — BLACK&DECKER 百得 BDH2000L无绳吸尘器 开箱
-
作者:初吻给了烟sco混迹张大妈时日不短了,手没少剁。家里有了汪星人,吸尘器使用频率相当高,偶尔零星打扫用卧式的实在麻烦(汪星人:你这分明是找借口,我掉毛是满屋子都有,铲屎君都是用卧式满屋子吸的,你...
- 专题|一个品牌一件产品(英国篇)之Quested(罗杰之声)
-
Quested(罗杰之声)代表产品:Q212FS品牌介绍Quested(罗杰之声)是录音监听领域的传奇品牌,由英国录音师RogerQuested于1985年创立。在成立Quested之前,Roger...
- 常用半导体中英对照表(建议收藏)(半导体英文术语)
-
作为一个源自国外的技术,半导体产业涉及许多英文术语。加之从业者很多都有海外经历或习惯于用英文表达相关技术和工艺节点,这就导致许多英文术语翻译成中文后,仍有不少人照应不上或不知如何翻译。为此,我们整理了...
- Fyne Audio F502SP 2.5音路低音反射式落地音箱评测
-
FyneAudio的F500系列,有新成员了!不过,新成员不是新的款式,却是根据原有款式提出特别版。特别版产品在原有型号后标注了SP字样,意思是SpecialProduction。Fyne一共推出...
- 有哪些免费的内存数据库(In-Memory Database)
-
以下是一些常见的免费的内存数据库:1.Redis:Redis是一个开源的内存数据库,它支持多种数据结构,如字符串、哈希表、列表、集合和有序集合。Redis提供了快速的读写操作,并且支持持久化数据到磁...
- RazorSQL Mac版(SQL数据库查询工具)
-
RazorSQLMac特别版是一款看似简单实则功能非常出色的SQL数据库查询、编辑、浏览和管理工具。RazorSQLformac特别版可以帮你管理多个数据库,支持主流的30多种数据库,包括Ca...
你 发表评论:
欢迎- 一周热门
-
-
前端面试:iframe 的优缺点? iframe有那些缺点
-
带斜线的表头制作好了,如何填充内容?这几种方法你更喜欢哪个?
-
漫学笔记之PHP.ini常用的配置信息
-
其实模版网站在开发工作中很重要,推荐几个参考站给大家
-
推荐7个模板代码和其他游戏源码下载的网址
-
[干货] JAVA - JVM - 2 内存两分 [干货]+java+-+jvm+-+2+内存两分吗
-
正在学习使用python搭建自动化测试框架?这个系统包你可能会用到
-
织梦(Dedecms)建站教程 织梦建站详细步骤
-
【开源分享】2024PHP在线客服系统源码(搭建教程+终身使用)
-
2024PHP在线客服系统源码+完全开源 带详细搭建教程
-
- 最近发表
-
- Mysql和Oracle实现序列自增(oracle创建序列的sql)
- 关于Oracle数据库12c 新特性总结(oracle数据库19c与12c)
- MySQL CREATE TABLE 简单设计模板交流
- mysql学习9:创建数据库(mysql5.5创建数据库)
- MySQL面试题-CREATE TABLE AS 与CREATE TABLE LIKE的区别
- Nike Dunk High Volt 和 Bright Spruce 预计将于 12 月推出
- 美国多功能舰载雷达及美国海军舰载多功能雷达系统技术介绍
- 汽车音响怎么玩,安装技术知识(汽车音响怎么玩,安装技术知识视频)
- 【推荐】ProAc Response系列扬声器逐个看
- #本站首晒# 漂洋过海来看你 — BLACK&DECKER 百得 BDH2000L无绳吸尘器 开箱
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)