今晚看代码的时候看到工厂类中方法和参数都使用static修饰,于是很好奇的想为什么一定要使用静态方法。百度了一下,发现百度了一堆垃圾,根本没有找到自己想要的答案。后来去Stack Overflow,果然找到了相关的问题。因为是英文的,所以翻译过来并综合整理了一下。

  为什么要在工厂模式中使用静态方法

  工厂模式是一种封装对象创建的方法。如果不使用工厂模式,你需要直接使用构造方法来创建对象:


Foo x = new Foo()


  使用工厂模式,可以取而代之的调用工厂方法:


Foo x = Foo.create()


  工厂类的构造方法被标记为private,所以构造方法除了在类的内部被调用以外不能够被访问。工厂类的其他方法被标记为static,这样不需要在调用该方法之前必须首先拥有一个该类的对象。

  使用工厂模式有一些好处。其一工厂类可以从许多子类(subclasses)(或者一个接口的实现)并返回它( One is that the factory can choose from many subclasses (or implementers of an interface) and return that. )。用这种方式调用方法可以通过参数来确定类的行为而不需要知道或者理解类的潜在的复杂层次(This way the caller can specify the behavior desired via parameters, without having to know or understand a potentially complex class hierarchy.)。

  另一个好处是,控制对一个有些资源的访问,比如数据库连接(connection)。这是一种实现重用对象池(pools of reusable objects)的方法而不是简单粗暴的先实例化对象,然后使用并销毁对象。如果实例化和销毁对象的代价很高,那么建立一次并重复使用对象显得意义非凡了。工厂方法可以返回一个已经实例化了但么有被使用的对象;或者如果对象数量小于指定的对象数量时,可以直接实例化一个对象;或者如果对象数量大于了指定的对象数量的时抛出异常并返回null。

  下面是一个数据库连接的工厂类的简单实现:


public class DbConnection
{
   private static final int MAX_CONNS = 100;
   private static int totalConnections = 0;

   private static Set<DbConnection> availableConnections = new HashSet<DbConnection>();

   private DbConnection()
   {
     // ...
     totalConnections++;
   }

   public static DbConnection getDbConnection()
   {
     if(totalConnections < MAX_CONNS)
     {
       return new DbConnection();
     }

     else if(availableConnections.size() > 0)
     {
         DbConnection dbc = availableConnections.iterator().next();
         availableConnections.remove(dbc);
         return dbc;
     }

     else
       throw new NoDbConnections();
   }

   public static void returnDbConnection(DbConnection db)
   {
     //...
   }
}