第一次看到这个名词是在Effective的第一条中,书中先是数落了一番构造器之后提出静态工厂方法的好处如何如何。看完后觉得,虽然这个名词之前没听过,其实在开发途中用的不少,入类型转换valueOf(),单例模式中的getInstance()均有静态工厂模式的痕迹。首先是不太认可书中所说的好处,于是上网寻找资料。总结如下:

一、什么是静态工厂方法

  其又叫简单工厂模式,与工厂模式不同,其是通过专门定义一个类来负责创建其他类的实例,其实例通常拥有共同父类,其普遍实现主要依靠Java的反射机制。

二、好处怎么体现

  Effective Java中共提到好处四点:

  1、它们有名称

  2、它们可以返回原返回类型任意子类型的对象。

  针对于第一点,相比较于与类名相同的构造函数,静态工厂方法是通过静态方法进行对象的初始化,其方法名字自然可以自定义,从而帮助开发人员的理解,这是容易理解的。例如,重载而来的构造函数,很难在不看源码的情况下知道他们的区别。

  第二点,其在Java中的集合类Collections用的颇多,主要利用Java的多态的特性,使得工厂可以产生基类的同时注入子类实现。

  如:

1 public interface Food {
2 
3     /**
4      * 使得所有食物都有一个共有的introduce方法
5      */
6     public void introduce();
7 }
 1 /**
 2  * 定义食物的子类:鱼
 3  */
 4 public class Fish implements Food{
 5 
 6     @Override
 7     public void introduce() {
 8         System.out.println("i am a fish");
 9     }
10 }
1 /**
2  * 食物的子类,水果
3  */
4 public class Fruit implements Food {
5     @Override
6     public void introduce() {
7         System.out.println("i am the fruit");
8     }
9 }
 1 /**
 2  * 通过反射机制实现的工厂
 3  */
 4 public class FoodFactory {
 5 
 6     public static Food getFood(String type) {
 7         Food food = null;
 8         try {
 9             food = (Food) Class.forName("info.zhw." + type).newInstance();
10         } catch (ClassNotFoundException e) {
11             e.printStackTrace();
12         } catch (InstantiationException e) {
13             e.printStackTrace();
14         } catch (IllegalAccessException e) {
15             e.printStackTrace();
16         }
17         return food;
18     }
19 }

  FoodFactory就利用了基类,返回了该类型的子类型。

 

  3、不必在每次调用他们的时候都创建一次对象。

  使用构造函数,调用其中的方法,则实例化一个类是必不可少的步奏,而是使用静态工厂方法,则可以对对象进行重复利用,这个特点在单例模式中使用颇多。

public class SingletonClass{
    private static SingletonClass instance=null;
    public static SingletonClass getInstance()
    {
        if(instance==null)
        {
            synchronized(SingletonClass.class)
            {
                if(instance==null)
                    instance=new SingletonClass();
            }
        }
        return instance;
    }
    private SingletonClass(){
    }
}

其将构造方法私有,只能通过getInstance()获取实例,从而达到实例重复利用的目的。

  

  4、使代码简洁

  与第一点有点雷同,主要也是在方便理解的基础上作出的改进。

 

三、缺点从何体现

  1、如果类不含有公有或受保护构造器,就不能被子类化。

  2、和静态方法实际上没有任何区别。其无法在API文档中明确标出,推荐使用管用名称管理。

  以上是Effective Java中提到的缺点,不疼不痒的样子,也许是我理解不深入的缘故。

  3、网上摘录的一段(http://blog.163.com/zhuowh2006@126/blog/static/10182372420133220511247/)

  由于工厂类集中了所有实例的创建逻辑,这就直接导致一旦这个工厂出了问题,所有的客户端都会受到牵连;而且由于简单工厂模式的产品室基于一个共同的抽象类或者接口,这样一来,但产品的种类增加的时候,即有不同的产品接口或者抽象类的时候,工厂类就需要判断何时创建何种种类的产品,这就和创建何种种类产品的产品相互混淆在了一起,违背了单一职责,导致系统丧失灵活性和可维护性。而且更重要的是,简单工厂模式违背了“开放封闭原则”,就是违背了“系统对扩展开放,对修改关闭”的原则,因为当我新增加一个产品的时候必须修改工厂类,相应的工厂类就需要重新编译一遍。

 

四、总结

  废话一句,需要根据实际情况选择合适的解决方案,实现时多了一种考虑,在使用构造器之前,考虑下静态工厂方法吧。

posted on 2015-03-17 01:33  Sluggard  阅读(9140)  评论(1编辑  收藏  举报