(四)工厂方法模式详解(另附简单工厂的死亡之路) (一)

2014-11-24 10:41:11 · 作者: · 浏览: 0

文章开头首先非常感谢各位的支持,代理模式中提到了class文件(即字节码文件)的相关知识,有一位读者说想要看有关class文件的相关内容,我也意识到了这一点,所以以后如果有在讲解那个模式的过程当中用到了其它的技术,我会留一些篇幅去介绍这个技术,有关class文件的内容我也会看以后的模式当中有没有用到的地方顺便简单介绍一下,如果没有的话,我会在设计模式介绍完以后专门写一篇有关java字节码文件的相关内容。

本章我们继续讨论新的设计模式,在这之前,LZ先要给自己擦擦屁股。

如果你看过上一章的话,一定还记得那个恶心的elseif结构,这是简单工厂的诟病,也是LZ的心病,我们最好还是解决了这个问题再继续走下去。

简单工厂模式对修改开放,在规模相对不大的情况下(针对上章的描述,规模不大特指的servlet数量不多的情况下),其实这种设计还是可以接受的,因为我们永远不要忘记,规则只是用来指导你的,不是用来限制你的,只要设计合理,你的设计就是规则!

不过针对简单工厂模式,你可以认为它给我们提供了一个思路,就是我们其实可以省掉那些让人痛恨的xml配置,对于我们后续的优化有着一定指导意义。

就像上一章中的处理方式,很明显存在着隐患,那就是在servlet数量急剧上升的时候,工厂类就会变得非常臃肿和复杂,变得难以维护和阅读。本章LZ给各位读者介绍一种优化方式,可以采取一项JDK当中在1.5版本引入的技术,即注解,去消除那些elseif的逻辑判断。

我们可以参考struts2的做法,即每一个Servlet我们都可以采用注解去设置它的名称,或者叫url,然后我们让我们的简单工厂依据这个去实例化我们的servlet。

根据以上方案,我们需要按照以下步骤让我们的简单工厂彻底死翘翘。

1.需要声明一个注解,它可以用来给servlet标识它的名称。

2.需要声明一个注解的处理器,用来处理我们的注解,主要作用是通过一个CLASS文件,去获得它的注解信息。

3.基于性能,我们需要将servlet与名称的映射与应用的生命周期绑定,并且这份映射在整个应用当中有且仅有一份,且不可更改。

4.让我们用于分派请求的过滤器,使用映射信息将客户请求对应到相应的servlet去处理,并且将分派逻辑移回过滤器,从而彻底删除简单工厂,即ServletFactory。

特别说一下,这四步当中,其中第三步是可选的,但也是必须的,因为如果不做这种处理,那么你就等着你的项目N长时间打开一个网页吧。

以上是简单工厂给我们的启示,具体如何实现这样一个基于注解的请求分配的架构,LZ不再给各位一一演示,因为这已经只剩下一个堆积代码的过程,具体的实现方案已经有了,如果各位读者有兴趣,可以私底下尝试一下这种方式。

关于工厂方法模式,LZ翻遍了所有能找到的源码,想寻找一个让各位读者既能学习到新的东西,又能对工厂方法理解更深的现有的优秀框架的设计。经过跋山涉水,LZ决定还是拿数据库连接来说事,我知道你想说,我去,又是数据库连接。LZ只想说,我去,我们每天做的最多的就是增删改查好吗,其它的咱也不认识啊, 。

众所周知,为了统一各个数据库操作的标准,于是有了JDBC的API,它用于给我们这种被称作只会使用现成的东西的程序猿,提供一系列统一的,标准化的操作数据库的接口。其实JDBC的各个类或接口,就是我们操作数据库的过程中各个协助者的抽象,这样的设计是为了让我们对数据库的操作依赖于抽象,还记得我们在设计模式总纲中提到的一句话吗,用抽象构建框架,用细节扩展实现。

JDBC API(即抽象的接口或类)就是整个数据库操作的框架,而各个数据库的驱动就是那些细节。而我们的操作依赖于JDBC API,而不是任何一个具体数据库的细节。

JDBC是如何统一了数据库世界的呢?其实最主要的就是靠两个接口,就统一了世界。。。

来看第一个接口Driver,附上源码。

[java]
package java.sql;

import java.sql.DriverPropertyInfo;
import java.sql.SQLException;

/**
* The interface that every driver class must implement.
*/
public interface Driver {

Connection connect(String url, java.util.Properties info)
throws SQLException;

boolean acceptsURL(String url) throws SQLException;

DriverPropertyInfo[] getPropertyInfo(String url, java.util.Properties info)
throws SQLException;

int getMajorVersion();

int getMinorVersion();

boolean jdbcCompliant();
}

package java.sql;

import java.sql.DriverPropertyInfo;
import java.sql.SQLException;

/**
* The interface that every driver class must implement.
*/
public interface Driver {

Connection connect(String url, java.util.Properties info)
throws SQLException;

boolean acceptsURL(String url) throws SQLException;

DriverPropertyInfo[] getPropertyInfo(String url, java.util.Properties info)
throws SQLException;

int getMajorVersion();

int getMinorVersion();

boolean jdbcCompliant();
}

由于篇幅,LZ删掉了很多注释,只保留了这个类注释的第一句话,翻译过来是这是一个任何驱动类都必须实现的接口。多么霸气啊。也就是每个数据库厂商都必须实现这个接口来提供JDBC服务,即java数据库连接服务,来方便程序猿对数据库应用编程

我们先忽略掉下面的五个方法,第一个方法毫无疑问是这个接口中相对