java设计模式-工厂模式(springweb为例子)
一般而言,工厂模式分为3种,简单工厂模式,工厂方法模式,抽象工厂模式。这三种工厂模式逐层深入吧。
一,从springWeb.jar包使用抽象工厂模式的一个例子聊起
之前对spring各种痴迷,所以在需要发送http请求时,用了spring自带的http客户端,上代码:
import java.io.InputStream;
import java.net.URI;
import java.nio.charset.Charset; import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.StreamUtils; public class Client {
public static void main(String[] args) throws Exception{ URI uri = new URI("https://www.cnblogs.com/");
//新建一个抽象ClientHttpRequest工厂
ClientHttpRequestFactory chrf = new SimpleClientHttpRequestFactory();
//生产一个抽象ClientHttpRequest
ClientHttpRequest req = chrf.createRequest(uri, HttpMethod.GET);
//ClientHttpRequest执行execute方法
ClientHttpResponse res = req.execute();
InputStream is = res.getBody();
String strBody = StreamUtils.copyToString(is, Charset.forName("UTF-8"));
is.close();
System.out.println(strBody); }
}
上UML图,首先是工厂类:
产品类,因为产品类有点小复杂,先看产品类接口的定义,看这个产品类的定义,你会觉得spring搞那么复杂干嘛,为啥不直接开一个统一的接口HttpRequest,
把httpOutputMessage里面的getBody放进去就好了。
其实仔细想想,spring之所以这么设计,是遵循“接口隔离原则”。
为啥要遵循这个原则呢?因为看完spring-web-release.jar包后你会发现,httpMessage被三个接口所extends,分别是HttpOutputMessage,HttpInputMessage,HttpRequest。
这三个接口有十多个实现类,如果并在一起,在三个接口中就需要重复写3次。
再聊聊HttpOutputMessage,HttpInputMessage,这两个接口对于springMVC来说是重中之重,是springMVC传输的载体,后面我们聊springMVC框架时还会遇到他们。
再看具体的产品实现类,笔者比较喜欢把方法也放进类图里面,所以稍微显得有点臃肿。前面我们看到,clientHttpRequest接口一共有5个接口方法需要子类去实现。
我猜想spring是这样子想的:
1,先定义几个抽象类implement那个ClientHttpRequest接口,然后在抽象类中对clientHttpRequest中做基本的实现,和之前笔者分析spring.core.io包里面想法一模一样。
这是用到设计模式中的“模版方法”模式,不过模版方法比较简单,就不单独开帖聊了。
2,5个接口方法中,在AbstractClientHttpRequest中实现了getHeaders(),getBody(),execute()3个方法,
然后还不省事地给他的子类添加了两个抽象方法getBodyInternal(HttpHeaders headers),executeInternal(HttpHeaders headers),
再悄悄地告诉你,这两个抽象方法分别有一个抽象类和两个具体实现类实现了该抽象方法,也就是我们的产品实现类的类图还没有画完,下图只是画了冰山一角而已,不过管中窥豹可见一斑,将就看看吧。
3.剩下的两个接口方法,getURI,getMethod()方法在SimpleStreamingClientHttpRequest具体的实现类中实现。
4,最后再分析下SimpleBufferingClientHttpRequest这个最底层的实现类。getURI,getMethod()是在这个SimpleBufferingClientHttpRequest底层类实现的。同时第2点提到的两个不省事的抽象方法在SimpleBufferingClientHttpRequest的父抽象类AbstractBufferingClientHttpRequest已经进行了具体的实现。
5.总结,以上几个类基本上一个接口方法对应着一个@Override,我猜想这是为了符合里氏替换原则(每个父类能用的地方,他的子类替换过去不会有任何影响)。
其实我挺期待父类override祖父类的接口方法,而后,孙子类再override父类的方法的,好像很少有这种用法。
spring用到的这种工厂模式,应该是属于最复杂的抽象工厂模式吧,继承树,产品族什么的,真的好复杂。
回到刚开始的需求,其实如果只是要发起一个简单的http请求,用工厂方法模式或者简单工厂模式就可以了吧。
二:工厂方法模式和简单工厂模式
举个栗子,我们来砍掉上述抽象工厂的产品族等等的一些为了拓展而抽象出的类和接口,类图会变成这个样子。
笔者故意比上面的类图多画了一个工厂实现类,让ClientHttpRequestFactory这个接口不会显得很鸡肋。用工厂方法模式其实已经能很大程度地增加程序的拓展性了。
将OkHttp3ClientHttpRequestFactory这个工厂具体实现类删掉,就变成了简单工厂模式的类图了。
至此,3种工厂模式已经介绍完了,如有错漏,还请各位博友批评指正。
java设计模式-工厂模式(springweb为例子)的更多相关文章
- 【设计模式】Java设计模式 -工厂模式
[设计模式]Java设计模式 -工厂模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! 目 ...
- 一张图搞定Java设计模式——工厂模式! 就问你要不要学!
小编今天分享的内容是Java设计模式之工厂模式. 收藏之前,务必点个赞,这对小编能否在头条继续给大家分享Java的知识很重要,谢谢!文末有投票,你想了解Java的哪一部分内容,请反馈给我. 获取学习资 ...
- Java设计模式---工厂模式(简单工厂、工厂方法、抽象工厂)
工厂模式:主要用来实例化有共同接口的类,工厂模式可以动态决定应该实例化那一个类.工厂模式的形态工厂模式主要用一下几种形态:1:简单工厂(Simple Factory).2:工厂方法(Factory M ...
- Java设计模式の工厂模式
-------------------------------------------------------- 目录: 一.序言 二.简单工厂模式 三.工厂方法模式 四.简单工厂和工厂方法模式的比 ...
- 10.Java设计模式 工厂模式,单例模式
Java 之工厂方法和抽象工厂模式 1. 概念 工厂方法:一抽象产品类派生出多个具体产品类:一抽象工厂类派生出多个具体工厂类:每个具体工厂类只能创建一个具体产品类的实例. 即定义一个创建对象的接口(即 ...
- 学习:java设计模式—工厂模式
一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类: 1)简单工厂模式(Simple Facto ...
- java设计模式—工厂模式
一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factor ...
- Java设计模式——工厂模式
一.工厂模式分类 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类: (1)简单工厂模式(Simp ...
- 1.Java设计模式-工厂模式
1.简单工厂模式(Factory Method) 常用的工厂模式是静态工厂模式,利用static修饰方法,作为一种类似于常见的工具类Utils等辅助效果,一般情况下工厂类不需要实例化. //1.定义一 ...
随机推荐
- 使用electron将应用程序加入到系统托盘
博主电脑
- 数据库Mysql的安装及操作---数据引擎
一.1.什么是数据 描述事物的符号记录称为数据. 2.什么是数据库 存放数据的仓库,只不过这个仓库在计算机上存储设备上. 二.Mysql的介绍 ...
- CentOS文件权限管理
目录 文件属性 chown更改所有者 chgrp更改所属组 文件权限rwx chmod修改权限 默认权限umask 权限判定的顺序 特殊权限SUID,SGID,sticky 隐藏权限chattr,ls ...
- Oracle SQL*Plus 数据备份为 sql 文件
在某些比较严格的环境中,不提供像PL/SQL Developer 这样的工具供我们备份表数据时,使用SQL*Plus运行如下脚本内容导出数据. 1, 执行时登录SQL*Plus, 命令 @D: ...
- 每天学点SpringMVC-异常处理
1. 第一步先写个Hello World 1.1 编写一个抛出异常的目标方法 @RequestMapping("/testException.do") public String ...
- JS之脚本延迟
自从开了博客,我就一下班回来匆匆吃完饭门一关等一开电脑一打开匆匆的研究东西,以至于朋友们都怀疑我是不是都得了自闭症 其实因为我有恐惧心理怕自己的技术哪天跟不上社会了,说到技术我觉得技术不求越新越好,但 ...
- hdu3018欧拉回路题
Ant Trip Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- git gc -- 压缩历史信息
格式: git gc [选项] <path> 选项 git commit -a 提交所有改动的文件(a -- all) NOTE: XX 举例 压缩历史消息 git ...
- Python面试题之copy/deepcopy详解
copy和deepcopy有什么区别? http://blog.csdn.net/qq_32907349/article/details/52190796 http://iaman.actor/blo ...
- Jquery使用mouseenter和mouseleave实现鼠标经过弹出层且可以点击
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Jquery使用mousee ...