第一次看到这个名词是在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/)
由于工厂类集中了所有实例的创建逻辑,这就直接导致一旦这个工厂出了问题,所有的客户端都会受到牵连;而且由于简单工厂模式的产品室基于一个共同的抽象类或者接口,这样一来,但产品的种类增加的时候,即有不同的产品接口或者抽象类的时候,工厂类就需要判断何时创建何种种类的产品,这就和创建何种种类产品的产品相互混淆在了一起,违背了单一职责,导致系统丧失灵活性和可维护性。而且更重要的是,简单工厂模式违背了“开放封闭原则”,就是违背了“系统对扩展开放,对修改关闭”的原则,因为当我新增加一个产品的时候必须修改工厂类,相应的工厂类就需要重新编译一遍。
四、总结
废话一句,需要根据实际情况选择合适的解决方案,实现时多了一种考虑,在使用构造器之前,考虑下静态工厂方法吧。