java模式之工廠模式和抽象工廠模式

工廠模式是創建模式,什麼是工廠模式呢。顧名思義,我們的社會發展了,以前是作坊式的,現在是工廠式了。生產產品不需要一家一家作坊式的生產了,放到工廠裏一起生產。再舉個通俗的例子,以前找人才一個個的找,現在有了人才市場,就跑到人才市場統一找,多方便啊。


採用工廠模式主要是爲了解決新類型對象的增加對原來系統的影響,當然這影響越小越好。所以工廠模式實現了創建實例與使用實例的分開,
把創建實例集中在一起控制,這樣,新類型對象的增加只侷限於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 方法. 然後再按模式和以上步驟來定義具體的類.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章