肥宅兜

导航

简单工厂模式

简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。

 

为什么要使用简单工厂模式

原因很简单:解耦。

A对象如果要调用B对象,最简单的做法就是直接new一个B出来。这么做有一个问题,假如C类和B类实现了同一个接口/继承自同一个类,系统需要把B类修改成C类,程序不得不重写A类代码。如果程序中有100个地方new了B对象,那么就要修改100处。

这就是典型的代码耦合度太高导致的"牵一发动全身"。所以,有一个办法就是写一个工厂IFactory,A与IFactory耦合,修改一下,让所有的类都实现C接口并且IFactory生产出C的实例就可以了。

 

就拿登录功能来说,假如应用系统需要支持多种登录方式如:口令认证、域认证(口令认证通常是去数据库中验证用户,而域认证则是需要到微软的域中验证用户)。那么自然的做法就是建立一个各种登录方式都适用的接口,如下图所示:

 

 

 

 

我们还需要一个工厂类LoginManager,根据调用者不同的要求,创建出不同的登录对象并返回。而如果碰到不合法的要求,会返回一个Runtime异常

 

 

 

简单工厂模式的结构如下图:

 

我们可以设想一下真实的场景,如果把上面的Test当做一个servlet的话,当客户端发起登录请求——>请求交给服务端的Servlet——>Servlet根据客户端传递的loginType调用工厂类LoginManager的factory()方法——>factory()方法根据参数loginType创建相应的登录验证类(DomainLogin或PasswordLogin)并返回——>登录验证类调用方法verify()验证用户名密码是否正确

假如不使用简单工厂模式则验证登录Servlet代码如下(假设Test为一个Servlet,变量loginType、name、password表示从客户端传递过来的参数):

 

 

public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub

String loginType = "password";
String name = "name";
String password = "password";
//处理口令认证
if(loginType.equals("password")){
PasswordLogin passwordLogin = new PasswordLogin();
boolean bool = passwordLogin.verify(name, password);
if (bool) {
/**
* 业务逻辑
*/
} else {
/**
* 业务逻辑
*/
}
}
//处理域认证
else if(loginType.equals("passcode")){
DomainLogin domainLogin = new DomainLogin();
boolean bool = domainLogin.verify(name, password);
if (bool) {
/**
* 业务逻辑
*/
} else {
/**
* 业务逻辑
*/
}
}else{
/**
* 业务逻辑
*/
}
}
}

 

 

 

 

 

 

 

 

当然,这么写其实也有一点点问题,假如有一天我的项目想进行一个重构,重整类路径,包路径,比方说生产Apple的地方有100处,岂不是要修改100处?当然不用,有以下三种方法推荐:

1、写一个接口FruitPath,里面定义常量:

public interface FruitPath
{
    public final static String apple = "com.xrq.simplefactory.Apple";
    public final static String grape = "com.xrq.simplefactory.Grape";
}

2、写一个Fruit.properties文件,里面定义水果和类路径的对应关系:

Apple=com.xrq.simplefactory.Apple
Grape=com.xrq.simplefactory.Grape

3、写一个Fruit.xml文件,里面定义水果和类路径的对应关系:

<apple>com.xrq.simplefactory.Apple</apple>
<grape>com.xrq.simplefactory.Grape</grape>

第一种方式不说了,第二种方式.properties可以用Java自带的Properties类来解析,第三种方式.xml可以用DOM4J来解析。这样, 假设我以后要修改水果的路径,修改一个文件就可以了。

从设计模式的角度讲,这么修改也有很大的优点。现在不管我新增还是删除水果,园丁(类工厂)都不用变了,只需要告诉工厂我需要哪种水果就够了,工厂自然会给调用者返回。这种写法,也是Spring的基础。

最后说一点,希望大家明白,简单工厂模式或者说工厂模式的关注点并不在于在工厂中是如何生产出来需要的类的,而在于将创建产品与消费产品分离。前面使用过if...else if...else、反射,除了这些方法,还可以有别的方法可以创建产品,比如传入一个具体产品的标识,根据这个标识去数据库里面查询。

 

简单工厂模式在Java中的应用及解读

以后每一篇文章尽可能地介绍设计模式在Java中的应用,因为我认为不是每种设计模式开发者都有机会可以用到,但是能在原有代码中敏锐地看出这是一种什么设计模式,至少能说明对这种设计模式是理解了。这里讲一下JDK中的简单工厂模式。

JDK中的简单工厂模式有很多应用,比较典型的比如线程池。我们使用线程池的时候,可以使用ThreadPoolExecutor,根据自己的喜好传入corePoolSize、maximumPoolSize、keepAliveTimem、unit、workQueue、threadFactory、handler这几个参数,new出一个指定的ThreadPoolExecutor出来。

JDK给开发者提供了Executors这个类,可以让用户产生ThreadPoolExecutor和使用ThreadPoolExecutor分离开,比如可以让Executors提供一个单线程的线程池Executors.newSingleThreadExecutor()、让Executors提供一个无界线程池Executors.newCachedThreadPool()等,这样,开发者可以不用关心线程池是如何去实现的,直接使用Executors方法提供给开发者的ThreadPoolExecutor就可以了。

 

工厂模式的优缺点

优点:

1、简单优化了软件体系结构,明确了各自功能模块的职责和权利

2、通过工厂类,外界不需要直接创建具体产品对象,只需要负责消费,不需要关心内部如何创建对象

缺点:

1、改进前的简单工厂模式全部创建逻辑都集中在一个工厂类中,能创建的类只能是考虑到的,如果需要添加新的类,就必须改变工厂类了

2、改进前的简单工厂模式随着具体产品的不断增多,可能会出现共产类根据不同条件创建不同实例的需求,这种对条件的判断和对具体产品类型的判断交错在一起,很难避免功能模块的蔓延,对系统的维护和扩展不利

3、改进后的简单工厂模式主要是使用反射效率会低一些

 

posted on 2016-07-23 21:12  肥宅兜  阅读(333)  评论(0编辑  收藏  举报