一般而言,工厂模式分为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为例子)的更多相关文章

  1. 【设计模式】Java设计模式 -工厂模式

    [设计模式]Java设计模式 -工厂模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! 目 ...

  2. 一张图搞定Java设计模式——工厂模式! 就问你要不要学!

    小编今天分享的内容是Java设计模式之工厂模式. 收藏之前,务必点个赞,这对小编能否在头条继续给大家分享Java的知识很重要,谢谢!文末有投票,你想了解Java的哪一部分内容,请反馈给我. 获取学习资 ...

  3. Java设计模式---工厂模式(简单工厂、工厂方法、抽象工厂)

    工厂模式:主要用来实例化有共同接口的类,工厂模式可以动态决定应该实例化那一个类.工厂模式的形态工厂模式主要用一下几种形态:1:简单工厂(Simple Factory).2:工厂方法(Factory M ...

  4. Java设计模式の工厂模式

    -------------------------------------------------------- 目录:  一.序言 二.简单工厂模式 三.工厂方法模式 四.简单工厂和工厂方法模式的比 ...

  5. 10.Java设计模式 工厂模式,单例模式

    Java 之工厂方法和抽象工厂模式 1. 概念 工厂方法:一抽象产品类派生出多个具体产品类:一抽象工厂类派生出多个具体工厂类:每个具体工厂类只能创建一个具体产品类的实例. 即定义一个创建对象的接口(即 ...

  6. 学习:java设计模式—工厂模式

    一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类: 1)简单工厂模式(Simple Facto ...

  7. java设计模式—工厂模式

    一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factor ...

  8. Java设计模式——工厂模式

    一.工厂模式分类 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类: (1)简单工厂模式(Simp ...

  9. 1.Java设计模式-工厂模式

    1.简单工厂模式(Factory Method) 常用的工厂模式是静态工厂模式,利用static修饰方法,作为一种类似于常见的工具类Utils等辅助效果,一般情况下工厂类不需要实例化. //1.定义一 ...

随机推荐

  1. 201521123110 《Java程序设计》第1周学习总结

    第一周学习总结 本周开始了对java的初次学习接触,Java是一门新的编程语言不同于C,由于有了c的基础,对于Java的理解和学习也相对从前学C更容易些. 也学习了Java的诞生发展以及运用包括JVN ...

  2. Git的使用详解

    起步 关于版本控制 Git 简史 Git 基础 安装 Git 初次运行 Git 前的配置 获取帮助 小结 Git 基础 取得项目的 Git 仓库 记录每次更新到仓库 查看提交历史 撤消操作 远程仓库的 ...

  3. 添加事务后 org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type available

    今天遇到了一个奇怪的问题   在没添加事务之前  所有的代码都是好的 , 当我添加了事务之后, 代码报错 org.springframework.beans.factory.NoSuchBeanDef ...

  4. Servlet学习应该注意的几点

    一.Servlet生命周期(即运行过程) (1)初始阶段,调用init()方法 (2)响应客户请求阶段,调用service()方法.由service()方法根据提交方式不同执行doGet()或doPo ...

  5. 多年iOS开发经验总结

    总结了几个月的东西终于能和大家分享了,不多说,直接看东西! 1.禁止手机睡眠 1 [UIApplication sharedApplication].idleTimerDisabled = YES; ...

  6. 编码格式简介:ASCII码、ANSI、GBK、GB2312、GB18030和Unicode、UTF-8,BOM头

    编码格式简介:ASCII码.ANSI.GBK.GB2312.GB18030和Unicode.UTF-8,BOM头 二进制: 只有0和1. 十进制.十六进制.八进制: 计算机其实挺笨的,它只认识0101 ...

  7. Ubuntu升级出现/boot空间不足解决

    经常升级Linux内核,导致更新时警告/boot分区空间不足.这是以为多次升级内核后,导致内核版本太多,清理一下没用的内核文件就行了.命令如下: zht@zht-Ubuntu:~$ dpkg -l ' ...

  8. web.xml中servlet-mapping的配置

    <servlet-mapping>元素在Servlet和URL样式之间定义一个映射.它包含了两个子元素<servlet- name>和<url-pattern>,& ...

  9. 关于离线底图和离线shp文件的加载

    首先底图是我自己用百度地图18级别的瓦片图在armap中制作的TPK文件,shp图层是我用同样的百度地图18级别的瓦片图矢量化的,二者在arcmap中的空间参考是一致的,所以我以为在移动端加入的时候二 ...

  10. 在CentOS7上通过RPM安装实现LAMP+phpMyAdmin过程全记录

    在CentOS7上通过RPM安装实现LAMP+phpMyAdmin过程全记录 时间:2017年9月20日 一.软件环境: IP:192.168.1.71 Hostname:centos73-2.sur ...