工廠模式是創建模式,什麼是工廠模式呢。顧名思義,我們的社會發展了,以前是作坊式的,現在是工廠式了。生產產品不需要一家一家作坊式的生產了,放到工廠裏一起生產。再舉個通俗的例子,以前找人才一個個的找,現在有了人才市場,就跑到人才市場統一找,多方便啊。
採用工廠模式主要是爲了解決新類型對象的增加對原來系統的影響,當然這影響越小越好。所以工廠模式實現了創建實例與使用實例的分開,把創建實例集中在一起控制,這樣,新類型對象的增加只侷限於Factory對象中。
注意以上說的工廠模式其實包括工廠模式和抽象工廠模式。
抽象工廠模式在創建對象實例上稍微比較複雜一點,舉個例子,
一個農場中由一個人來管理農場中的所有產品,這就是簡單工廠模式,這種模式只適合小的農場。
當農場規模擴大後,一個人來管理顯示不合適,這時就需要多個人來管理,相當於有多個具體工廠類,每個人管理不同的產品,如張三管理大白菜,李四來管理蘋果,這是工廠模式.
如果農場進一步擴大,比如大白菜這個品種,有北方的大白菜,有南方的大白菜,或者更多,其它的產品與大白菜類似,分成許多地域的品種,這時就要採用抽象工廠模式。
農場的抽象工廠模式:
一個抽象產品類,用來管理南方的產品,包括大白菜等
另一個抽象產品類,用來管理北方的產品,包括大白菜等
一個抽象工廠類,多個具體工廠類,其中一個專門管理各地的大白菜,其它類似。
一般情況下使用工廠類的比較多,如之前我們做過的項目,對於operator對象的生成使用的都是工廠模式。
Operator operator = (Operator) Class.forName(name.trim())
.newInstance();
根據關鍵字name的不同動態取得不同的operator對象。源代碼如下:
public class OperatorFactoryImpl implements OperatorFactory{
private static final Logger logger = Logger.getLogger(OperatorFactoryImpl.class);
private static OperatorFactoryImpl instance = new OperatorFactoryImpl();
private static final String KEY_MAPPING_PROPERTIES="operatorMapping.properties";
public static OperatorFactoryImpl getInstance(){
return instance;
}
public OperatorFactoryImpl(){
Properties p = new Properties();
try {
p.load(getClass().getResourceAsStream(KEY_MAPPING_PROPERTIES));
Enumeration en =p.keys();
while(en.hasMoreElements()){
String key = en.nextElement().toString();
operators.put(key,p.get(key));
}
} catch (IOException e) {
e.printStackTrace();
}
}
private HashMap operators = new HashMap();
public Operator create(String key) {
String name = (String)operators.get(key);
logger.debug("the name is "+name);
if(name!=null){
try {
Operator operator = (Operator) Class.forName(name.trim())
.newInstance();
return operator;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return null;
}
}
下面舉例一個DAO模式中實現抽象工廠,順便也看看是怎麼使用DAO模式的。
爲DAO實現工廠類的策略
1 採用工廠方法設計模式
如果一個DAO 工廠只爲一個數據庫的實現,(比如ORACLE)而創建很多的DAO的時候,實現該策略時,我們考慮採用工廠方法設計模式. 假設該工廠
類創建了CustomerDAO, AccountDAO, OrderDAO 等一些對象。
2 使用抽象工廠設計模式:
如果考慮爲三種不同類型的數據庫來實現這個策略,我們可以考慮採用抽象工廠設計模式. 假設. 這個工廠創建了CustomerDAO, AccountDAO,
OrderDAO的一系列的DAO, 該策略運用了在抽象工廠中產生的工廠類中的工廠方法的實現.
代碼說明:
以下代碼舉例說明了DAO設計模式的具體實現:
我們以使用抽象工廠的設計模式來對付多種類型數據庫爲例,在以下的例子中只具體列出CLOUDSCAPE 數據庫類型的DAO設計模式的具體實現,其
他類型數據庫DAO設計模式的實現大同小異.
1 // Abstract class DAO Factory
public abstract class DAOFactory {
// List of DAO types supported by the factory
public static final int CLOUDSCAPE = 1;
public static final int ORACLE = 2;
public static final int SYBASE = 3;
...
// There will be a method for each DAO that can be
// created. The concrete factories will have to
// implement these methods.
// 所有實現該抽象工廠的工廠類中必須有的方法,用這些方法來創建具體的DAO類.
public abstract CustomerDAO getCustomerDAO();
public abstract AccountDAO getAccountDAO();
public abstract OrderDAO getOrderDAO();
//該抽象類的靜態方法,用他來創建其他具體的DAO工廠類
public static DAOFactory getDAOFactory(
int whichFactory) {
switch (whichFactory) {
case CLOUDSCAPE:
return new CloudscapeDAOFactory();
case ORACLE :
return new OracleDAOFactory();
case SYBASE :
return new SybaseDAOFactory();
...
default :
return null;
}
}
}
2 以下是Cloudscape DAO FACTORY 類的實現,在他裏面實現了該類型數據庫的連接,以及實現了他所繼承的抽象工廠類中所必須實現的那些方法
,在這些方法中創建具體的DAO對象.
// Cloudscape concrete DAO Factory implementation
import java.sql.*;
public class CloudscapeDAOFactory extends DAOFactory {
public static final String DRIVER=
"COM.cloudscape.core.RmiJdbcDriver";
public static final String DBURL=
"jdbc:cloudscape:rmi://localhost:1099/CoreJ2EEDB";
// method to create Cloudscape connections
//建立Cloudscape 連接
public static Connection createConnection() {
// Use DRIVER and DBURL to create a connection
// Recommend connection pool implementation/usage
}
//創建 CustomerDAO 對象 當然返回的是一個該類實現的接口,他的好處就是實現了實現細節的隱蔽.
public CustomerDAO getCustomerDAO() {
// CloudscapeCustomerDAO implements CustomerDAO
return new CloudscapeCustomerDAO();
}
//創建 AccountDAO 對象 當然返回的是一個該類實現的接口,他的好處就是實現了實現細節的隱蔽.
public AccountDAO getAccountDAO() {
// CloudscapeAccountDAO implements AccountDAO
return new CloudscapeAccountDAO();
}
//創建 OrderDAO 對象 當然返回的是一個該類實現的接口,他的好處就是實現了實現細節的隱蔽.
public OrderDAO getOrderDAO() {
// CloudscapeOrderDAO implements OrderDAO
return new CloudscapeOrderDAO();
}
...
}
3 以下代碼就是具體DAO類實現的接口也就是CloudscapeCustomerDAO()實現的接口: CustomerDAO .在該接口中定義了所有的業務方法.
// Interface that all CustomerDAOs must support
public interface CustomerDAO {
public int insertCustomer(...);
public boolean deleteCustomer(...);
public Customer findCustomer(...);
public boolean updateCustomer(...);
public RowSet selectCustomersRS(...);
public Collection selectCustomersTO(...);
...
}
4 以下CloudscapeCustomerDAO類實現的具體業務細節和數據操作細節, 他是要向客戶數據端隱蔽的.
import java.sql.*;
public class CloudscapeCustomerDAO implements
CustomerDAO {
public CloudscapeCustomerDAO() {
// initialization
}
// The following methods can use
// CloudscapeDAOFactory.createConnection()
// to get a connection as required
public int insertCustomer(...) {
// Implement insert customer here.
// Return newly created customer number
// or a -1 on error
}
public boolean deleteCustomer(...) {
// Implement delete customer here
// Return true on success, false on failure
}
public Customer findCustomer(...) {
// Implement find a customer here using supplied
// argument values as search criteria
// Return a Transfer Object if found,
// return null on error or if not found
}
public boolean updateCustomer(...) {
// implement update record here using data
// from the customerData Transfer Object
// Return true on success, false on failure or
// error
}
public RowSet selectCustomersRS(...) {
// implement search customers here using the
// supplied criteria.
// Return a RowSet.
}
public Collection selectCustomersTO(...) {
// implement search customers here using the
// supplied criteria.
// Alternatively, implement to return a Collection
// of Transfer Objects.
}
...
}
5 下面的代碼是數據客戶端向DAO中傳輸數據的, 他其實就是一個JAVABEAN;
public class Customer implements java.io.Serializable {
// member variables
int CustomerNumber;
String name;
String streetAddress;
String city;
...
// getter and setter methods...
...
}
6 最後就是客戶數據端對這個設計的應用:
...
// create the required DAO Factory
DAOFactory cloudscapeFactory =
DAOFactory.getDAOFactory(DAOFactory.DAOCLOUDSCAPE);
// Create a DAO
CustomerDAO custDAO =
cloudscapeFactory.getCustomerDAO();
// create a new customer
int newCustNo = custDAO.insertCustomer(...);
// Find a customer object. Get the Transfer Object.
Customer cust = custDAO.findCustomer(...);
// modify the values in the Transfer Object.
cust.setAddress(...);
cust.setEmail(...);
// update the customer object using the DAO
custDAO.updateCustomer(cust);
// delete a customer object
custDAO.deleteCustomer(...);
// select all customers in the same city
Customer criteria=new Customer();
criteria.setCity("New York");
Collection customersList =
custDAO.selectCustomersTO(criteria);
// returns customersList - collection of Customer
// Transfer Objects. iterate through this collection to
// get values.
言而簡之,以下6步完成該模式的實現:
1 創建一個抽象工廠類,他包含兩個重要的部分: 第一部分是 一些抽象方法,這些方法是所有實現該抽象工廠的具體工廠類所必須實現的. 第二
部分 就是一個靜態方法,該方法來創建一個具體類型數據源的工廠對象,比如文中的CloudscapeDAOFactory().
2 然後,分別創建各個類型數據源的工廠類,(本文以CloudscapeDAOFactory爲例).在這個工廠類中裏面也有兩個重要組成部分: 第一部分就是實
現在他繼承的那個抽象工廠類中的左右抽象方法,在該方法中創建具體的DAO對象(這些對象的類在第4不具體定義實現),本文中三個方法分別創
建了3個具體的DAO對象,當然爲了實現細節的隱蔽,這些方法返回的是這些具體DAO類門實現的接口(這些接口在第3步實現).
3 定義具體DAO類的接口,並在接口中定義所有的業務方法,和數據操作方法.
4 定義具體的DAO類,在這個類中才是實際的業務方法,和數據的操作的實現.
5 定義數據傳輸對象,他是用來在客戶端和DAO之間傳遞數據的,他其實就是一個JAVABEAN.
6 完成以上5步之後我們就可以在數據客戶端使用以上由DAO設計模式定義好的各個類了(見最後一個代碼例子塊).
以上6步大家在編程的時需具體體會,一般來說,數據庫中的一個表就可以對應一個數據傳遞類也就是在第4步中定義的那個類,類中的屬性就是表
中的字段,然後加上相應的GET,SET 方法. 然後再按模式和以上步驟來定義具體的類.