一般而言,工厂模式分为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. Core Java 简单谈谈HashSet

    同学们在看这个问题的时候,我先提出者两个问题,然后大家带着问题看这个文章会理解的更好. HashSet为什么添加元素时不能添加重复元素? HashSet是否添加null元素? 打开源码, 我们看到如下 ...

  2. python 输出颜色的与样式的方法

    上次遇到这个问题就想写下来,其实当时我也不怎么会,老师说这个东西不需要理解,只需要死记硬背,写的多了就记住了,所以今天搜集了几篇文章,加上自己的理解,写下了这篇python 输出颜色的样式与方法的文章 ...

  3. Struts2第五篇【类型转换器、全局、局部类型转换器】

    前言 上篇博文已经讲解了,Struts2为我们实现了数据自动封装-由上篇的例子我们可以看出,表单提交过去的数据全都是String类型的,但是经过Struts自动封装,就改成是JavaBean对应成员变 ...

  4. 《Head First 设计模式》读书笔记(1) - 策略模式

    <Head First 设计模式>(点击查看详情) 1.写在前面的话 之前在列书单的时候,看网友对于设计模式的推荐里说,设计模式的书类别都大同小异,于是自己就选择了Head First系列 ...

  5. [js高手之路] 设计模式系列课程 - 迭代器(1)

    迭代器是指通过一种形式依次遍历数组,对象,或者类数组结构中的每个元素. 常见的有jquery中的each方法, ES5自带的forEach方法. 下面我们就来自定义一个类似jquery或者ES5的迭代 ...

  6. BZOJ2748_音量调节_KEY

    [HAOI2012]音量调节 Time Limit: 3 Sec Memory Limit: 128 MB Description 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以 ...

  7. thinkphp的select和find的区别

    hinkphp是比较好的php开发框架,能比较快速的开发MVC架构的管理系统,我们需要用到 select()和find()方法,两个方法都能返回数据集数组,但有什么不同呢?先看一下我的代码对比:$te ...

  8. C++ Primer Plus 6 第二章

    // myfirst.cpp--displays a message #include <iostream> // a PREPROCESSOR directive int main() ...

  9. R语言基础语法

    学习一门新的语言,率先学习输出hello world.我们就从这里开始学习. 首先打开RStudio这个IDE,然后在左边输入: > mystr <- "hello world& ...

  10. 原生JS封装animate运动框架

    <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...