為什麼要在JAVA工廠模式中使用靜態方法

snake_hand發表於2013-04-05

今晚看程式碼的時候看到工廠類中方法和引數都使用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)
   {
     //...
   }
}

 

多個工廠方法也可以允許對相似引數型別的不同解析。通常構造方法有與類相同的名字,這意味著如果給定一個簽名(signature)你就只能擁有一個構造方法。工廠模式則沒有這麼多的限制。也就是說你可以有不同的方法但是卻接收相同的引數型別:

      

 Coordinate c = Coordinate.createFromCartesian(double x, double y)

 Coordinate c = Coordinate.createFromPolar(double distance, double angle)

 

這可以用來提高程式碼的可讀性。

比較下面的兩種不同方式:

public class Foo{
  public Foo(boolean withBar){
    //...
  }
}

//...

// What exactly does this mean?
Foo foo = new Foo(true);
// You have to lookup the documentation to be sure.
// Even if you remember that the boolean has something to do with a Bar
// you might not remember whether it specified withBar or withoutBar.
public class Foo{
  public static Foo createWithBar(){
    //...
  }

  public static Foo createWithoutBar(){
    //...
  }
}

// ...

// This is much easier to read!
Foo foo = Foo.createWithBar();

 

歡迎轉載,轉載請註明出處。

相關文章