今天看java編程思想中的接口時,理解不了工廠方法設計模式,希望有人能來幫忙解答下。
書上的代碼說的是在一個相同的棋盤上下國際象棋和西洋跳棋,
interface Game{...}
interfacd GameFactory{...}
class Checkers implements Game{...}
class CheckersFactory implements GameFactory
{
public Game getGmae() {return new Checkers();}
}
class Chess implements Game{...}
class ChessFactory implements GameFactory
{
public Game getGmae() {return new Chess();}
}
public class Games
{
public static void playGame(GameFactory factory)
{ Game s=factory.getGame();
}
public static void main(...)
{playGame(new CheckerFactory); playGame(new ChessFatory);}
}
這是書上的代碼,我省略了一些跟我問題無關的代碼。
我的問題是爲什麼要這麼麻煩,給Checkers和Chess都弄個工廠,然後從工廠裏返回類型,可以直接把public static void playGame(GameFactory factory) 改成
public static void playGame(Game factory)不就可以了嗎?然後playGame(new CheckerFactory); playGame(new ChessFatory);改成playGame(Checkers);
playGame(Chess); 利用向上轉型原理。這樣不是可以把上面的那些Factory代碼全刪掉麼?另外Factory模式到底有什麼用處。
可能是我沒有理解工廠方法設計模式。希望有人能來回答下。
---------------------
看你的例子更像是Abstract factory pattern,而不像是工廠方法設計模式factory method pattern。
在你的例子裏,如你所說的改動,看似沒什麼問題,在這裏game的構造過程很簡單new SomeGame()。
首先工廠模式在於其封裝了其產品(game)的構造過程。
考慮到複雜的構造過程,例如SomeGame構造需要配置多個參數,那麼getGame就要通過相應的途徑去取得這些參數,例如讀取配置文件。
在這種情況下,對於用戶main來說,就可以簡單的獲得Game而不需要清楚如何取構造它。
另一點,工廠模式在於其提供一個構造產品的方法。例如你做的是一個遊戲服務器,playGame會等待用戶連接,然後爲每一個用戶連接創建一個Game,那麼你可以簡單的gameFactory.getGame,而如果你把Game作爲參數傳遞就完全不同了。
---------------------------
這段程序據我的理解,並沒有深刻地表達工廠方法意義,可能讓你產生了誤解。按照你的方法來改也未嘗不可,但是它主要講的是工廠方法啊,所以就必須採用工廠來實現。
下面這些是原來幫別人回答類似問題時用到的代碼,你可以參考一下:
原文地址:http://community.csdn.net/Expert/TopicView3.asp?id=5658401
工廠方法指的是根據不同的情況產生不同的對象,比如:
public static Dao getDao(String dbmsName) throws UnsupportDatabaseException {
if( dbmsName.equalsIgnoreCase( "SQL Server ") ) {
return new SqlServerDao();
} else if( dbmsName.equalsIgnoreCase( "Oracle ") ) {
return new OracleDao();
} else if( dbmsName.equalsIgnoreCase( "MySQL ") ) {
return new MySQLDao();
} else {
throw new UnsupportDatabaseException(dbmsName);
}
}
其中 Dao 是 SqlServerDao、OracleDao、MySQLDao 的接口。
上面這段代碼就是一個典型的工廠方法,通過傳入的數據庫名稱來確定,並獲得不同的數據庫處理實現。若使用的數據庫並沒有實現,則進行異常處理。
不過一般不會這樣寫,這裏僅作個示例。我基本上是把當前 Dao 的實現類寫在 XML 中,在進行動態加載類操作,使用工廠返回 Dao 對象的。
如果是一個寫得比較好的工廠方法,要符合“開-閉原則”,在新增實現類後,只需更改配置,而原來寫好的源代碼根本不需要去修改。