一般而言,工厂模式分为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. php中的多条件查询

    首先是查询所有,步骤不详述,连接数据库,查询表中的所有信息,foreach循环以表格的形式打印出来 然后就是form表单中提交查询的数据,这里以post方式提交到本页面,所以要判断post中是否有值, ...

  2. MyBatis框架(一)

    MyBatis介绍: MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为 ...

  3. Spring - Bean的概念及其基础配置

    概述 bean说白了就是一个普通的java类的实例,我们在bean中写一些我们的业务逻辑,这些实例由Sping IoC容器管理着.在web工程中的spring配置文件中,我们用<bean/> ...

  4. JDBC数据库之添加数据

    通过JDBC向数据库中添加数据,可以使用INSERT语句实现插入数据SQL语句,对于SQL语句中的参数可以只用占位符"?"代替,然后通过PreparedStatement对其赋值以 ...

  5. SimpleRpc-网络事件响应Reactor设计模式

    前言 这篇文章主要介绍整个框架用到的最核的一个设计模式:反应器模式.这个设计模式可以在<面向对象的软件架构>中详细了解,没有这本书的小伙伴不要急,我通过咱们的SimpleRpc来告诉大家这 ...

  6. Redis学习笔记之二 :在Java项目中使用Redis

    成功配置redis之后,便来学习使用redis.首先了解下redis的数据类型. Redis的数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set( ...

  7. 【转】开源中国上看到的一个vim的自动配置的好东西,分享下

    https://www.oschina.net/p/onekey-to-vim-ide 变量有高亮,竖行上有直线定位,对python的支持效果更佳,从事C/C++开发的程序员使用也不错.

  8. oracle存储过程中is和as区别

    在存储过程(PROCEDURE)和函数(FUNCTION)中没有区别:在视图(VIEW)中只能用AS不能用IS:在游标(CURSOR)中只能用IS不能用AS.

  9. 关于数据库中datareader的用法

    1.C#中提供的DataReader可以从数据库中每次提取一条数据. using System; using System.Collections.Generic; using System.Comp ...

  10. const的用法,特别是用在函数前面与后面的区别!

    const的用法,特别是用在函数后面 在普通的非 const成员函数中,this的类型是一个指向类类型的 const指针.可以改变this所指向的值,但不能改变 this所保存的地址. 在 const ...