2010-04-23 36 views
5

Tôi muốn biết khi nào chúng ta cần sử dụng mẫu nhà máy trừu tượng.khi nào nên sử dụng mẫu nhà máy trừu tượng?

Đây là một ví dụ, tôi muốn biết nếu nó là cần thiết.

The UML

ở trên là Abstract Factory, nó được khuyến khích bởi bạn cùng lớp của tôi. Sau đây là triển khai myown. Tôi không nghĩ rằng nó là cần thiết để sử dụng các mô hình.

Và sau đây là một số mã lõi:

package net; 

import java.io.IOException; 
import java.util.HashMap; 
import java.util.Map; 
import java.util.Properties; 



public class Test { 
    public static void main(String[] args) throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException { 
     DaoRepository dr=new DaoRepository(); 
     AbstractDao dao=dr.findDao("sql"); 
     dao.insert(); 
    } 
} 

class DaoRepository { 
    Map<String, AbstractDao> daoMap=new HashMap<String, AbstractDao>(); 
    public DaoRepository() throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException { 
     Properties p=new Properties(); 
     p.load(DaoRepository.class.getResourceAsStream("Test.properties")); 
     initDaos(p); 
    } 
    public void initDaos(Properties p) throws InstantiationException, IllegalAccessException, ClassNotFoundException { 
     String[] daoarray=p.getProperty("dao").split(","); 
     for(String dao:daoarray) { 
      AbstractDao ad=(AbstractDao)Class.forName(dao).newInstance(); 
      daoMap.put(ad.getID(),ad); 
     } 
    } 
    public AbstractDao findDao(String id) {return daoMap.get(id);} 

} 
abstract class AbstractDao { 
    public abstract String getID(); 
    public abstract void insert(); 
    public abstract void update(); 
} 
class SqlDao extends AbstractDao { 
    public SqlDao() {} 
    public String getID() {return "sql";} 
    public void insert() {System.out.println("sql insert");} 
    public void update() {System.out.println("sql update");} 
} 
class AccessDao extends AbstractDao { 
    public AccessDao() {} 
    public String getID() {return "access";} 
    public void insert() {System.out.println("access insert");} 
    public void update() {System.out.println("access update");} 
} 

Và nội dung của Test.properties chỉ là một dòng:

dao=net.SqlDao,net.SqlDao 

Vì vậy, bất kỳ ont có thể cho tôi biết nếu suitation này là cần thiết ?


------------------- Phần sau được thêm vào để giải thích sự phù hợp thực tế --------------

Tôi sử dụng ví dụ về Đạo là điều bình thường, mọi người đều biết điều đó.

Trong thực tế, những gì tôi đang làm việc hiện nay không liên quan đến DAO, tôi đang làm việc để xây dựng một dịch vụ Web

, các serivce web có chứa một số thuật toán để chang một tập tin sang định dạng khác,

Ví dụ: net.CreatePDF, net.CreateWord và vv, nó trưng ra hai giao diện cho máy khách: getAlgorithms và doProcess.

getAlogrithoms sẽ trả về tất cả id của thuật toán, mỗi id được thực hiện cho thuật toán tương ứng .

Người dùng gọi phương thức doProcess cũng sẽ cung cấp id thuật toán mà anh muốn.

Tất cả thuật toán mở rộng AbstractAlgorithm xác định phương thức run().

tôi sử dụng một AlogrithmsRepository để lưu trữ tất cả các thuật toán (từ

tập tin thuộc tính mà cấu hình các lớp java cụ thể của thuật toán bằng web

dịch vụ quản trị) Vững để nói, DoProcess giao diện tiếp xúc bởi dịch vụ web là

được thực hiện bởi alogrithm cụ thể.

tôi có thể cung cấp cho một ví dụ đơn giản: 1) người sử dụng gửi getAlgorithms yêu cầu:

http://host:port/ws?request=getAlgorithms 

Sau đó, người dùng sẽ nhận được một danh sách các thuật toán embeded trong một xml.

<AlgorithmsList> 
    <algorithm>pdf</algorithm> 
    <algorithm>word<algorithm> 
</AlgorithmsList> 

2) người dùng gửi một DoProcess đến máy chủ bằng cách:

http://xxx/ws?request=doProcess&alogrithm=pdf&file=http://xx/Test.word 

khi máy chủ Nhận các loại requst, nó sẽ nhận được dụ thuật toán cụ thể theo các tham số "thuật toán" (đó là pdf trong yêu cầu này) từ AlgorithmRepostory. Và gọi phương thức:

AbstractAlgorithm algo=AlgorithmRepostory.getAlgo("pdf"); 
algo.start(); 

Sau đó, tệp pdf sẽ được gửi tới người dùng.

BTW, trong ví dụ này, mỗi thuật toán tương tự như sqlDao, AccessDao. Dưới đây là hình ảnh:

The design image

Bây giờ, nào AlgorithmRepostory cần phải sử dụng Nhà máy Tóm tắt?

Trả lời

2

Sự khác biệt chính giữa hai cách tiếp cận là đầu sử dụng các nhà máy DAO khác nhau để tạo DAO trong khi phía dưới lưu trữ một bộ DAO và trả về tham chiếu đến DAO trong kho.

Phương pháp tiếp cận dưới cùng có vấn đề nếu nhiều chủ đề cần truy cập vào cùng một loại DAO một cách đồng thời vì các kết nối JDBC không được đồng bộ hóa.

Điều này có thể được khắc phục bằng cách yêu cầu DAO triển khai phương thức newInstance() chỉ đơn giản là tạo và trả về một DAO mới.

abstract class AbstractDao { 
    public abstract String getID(); 
    public abstract void insert(); 
    public abstract void update(); 
    public abstract AbstractDao newInstance(); 
} 
class SqlDao extends AbstractDao { 
    public SqlDao() {} 
    public String getID() {return "sql";} 
    public void insert() {System.out.println("sql insert");} 
    public void update() {System.out.println("sql update");} 
    public AbstractDao newInstance() { return new SqlDao();} 
} 

Các kho có thể sử dụng của DAO trong kho các nhà máy cho trả về bởi Repository (mà tôi sẽ đổi tên thành Nhà máy trong trường hợp đó) của DAO như thế này:

public AbstractDao newDao(String id) { 
    return daoMap.containsKey(id) ? daoMap.get(id).newInstance() : null; 
} 

Cập nhật

Đối với câu hỏi của bạn, dịch vụ web của bạn có nên triển khai một nhà máy hay nó có thể sử dụng kho lưu trữ như bạn đã mô tả không?Một lần nữa, câu trả lời phụ thuộc vào chi tiết:

  • Đối với dịch vụ web nó là bình thường để mong đợi nhiều khách hàng đồng thời
  • Do đó các trường hợp thực hiện quá trình cho hai khách hàng không được ảnh hưởng eachother
  • Có nghĩa họ không được chia sẻ tiểu bang
  • Nhà máy cung cấp bản sao mới trên mọi yêu cầu, do đó không có trạng thái nào được chia sẻ khi bạn sử dụng mẫu nhà máy
  • .210
  • Nếu (và chỉ nếu) các trường hợp trong kho của bạn là stateless web-dịch vụ của bạn cũng có thể sử dụng kho như bạn mô tả, cho này có lẽ họ cần phải nhanh chóng các đối tượng khác để thực sự thực hiện quá trình dựa trên yêu cầu thông số được thông qua
+0

@ rsp-Cảm ơn bạn đã khắc phục sự cố của tôi. Trong thực tế, điều tôi muốn làm rõ ràng là khi sử dụng một Nhà máy Tóm tắt, đó là để nói rằng chúng tôi giả định hai cách được đề cập ở trên không thể gây ra một số vấn đề về luồng. tốt, nếu các vấn đề không tồn tại, tại sao chúng ta sử dụng Abstract Factory? Trong mô hình Ab.Fatory, các sản phẩm khác nhau được tạo ra bởi các nhà máy khác nhau, theo cách sau (bạn đã sửa), các sản phẩm được tạo ra bởi một Kho lưu trữ (ví dụ DaoRepository), vậy sự khác biệt là gì? Khi Repository tạo một thể hiện mới, nó cũng không biết đối tượng nào đang tạo ra, phải không? – hguser

+0

@hguser, Như mọi khi, nó phụ thuộc vào ngữ cảnh. Nếu nhu cầu của bạn là để khởi tạo một tập hợp trên các đối tượng được sử dụng bởi các ứng dụng không có gì sai với một kho lưu trữ tạo ra các cá thể dựa trên cấu hình và đưa ra các tham chiếu đến các đối tượng này. Trong trường hợp này, "nhà máy" là một phần của việc khởi tạo kho lưu trữ.Một nhà máy đối tượng tạo ra các cá thể mới là một trường hợp sử dụng khác, có thể bao gồm nhiều công dụng hơn. – rsp

+0

@ rsp-Vì vậy, đối với tình huống tôi đã thêm (ví dụ về dịch vụ web), nếu muốn sử dụng nhà máy trừu tượng trong AlgorithmsRepository, làm thế nào để thực hiện nó? Tôi thực sự muốn nói rõ về sự khác biệt từ ví dụ tương tự. Cảm ơn. – hguser

2

Nếu bạn hỏi để so sánh 2 thiết kế từ UML, API thứ 2 trên UML đã sau bất lợi:

  • người gọi cần phải xác định rõ ràng loại DAO trong cuộc gọi đến getDAO(). Thay vào đó, người gọi không nên quan tâm đến loại DAO nó hoạt động với, miễn là DAO tuân thủ giao diện. Thiết kế đầu tiên cho phép người gọi chỉ cần gọi createDAO() và nhận giao diện để làm việc. Cách thức kiểm soát việc sử dụng hàm này linh hoạt hơn và người gọi không có trách nhiệm này, điều này giúp cải thiện tính mạch lạc tổng thể của thiết kế.
+0

Nhưng nhà máy trừu tượng cũng cần được chăm sóc người gọi về loại. http://java.dzone.com/articles/design-patterns-abstract-factory Bài viết này, theo phương pháp chính, người dùng phải konw rằng có hai typs, MsWindowsWidgetFactory và MACOSWindowsWidgetFactory. – hguser

+0

@hguser - một nơi nào đó trong chuỗi cuộc gọi, ai đó cần phải chỉ định loại, nhưng người gọi * ngay lập tức * của nhà máy trừu tượng không cần phải biết loại nhà máy. –

+0

@Jeff Sternal - http://dpaste.org/GyRC/ Dòng 9 và 13, chúng tôi gọi nhà máy là manully bằng từ "mới". – hguser

0

Nhà máy trừu tượng rất hữu ích nếu bạn cần tách nhiều kích thước lựa chọn để tạo thứ gì đó.

Trong trường hợp ví dụ điển hình của hệ thống cửa sổ, bạn muốn tạo một nhóm tiện ích cho các hệ thống cửa sổ loại và bạn tạo một nhà máy cụ thể trên mỗi hệ thống cửa sổ để tạo các tiện ích hoạt động trong hệ thống đó.

Trong trường hợp xây dựng DAO, có thể hữu ích nếu bạn cần tạo một DAO cho các thực thể trong miền của bạn và muốn tạo phiên bản "sql" và phiên bản "truy cập" của toàn bộ gia đình. Đây là tôi nghĩ rằng điểm mà bạn cùng lớp của bạn đang cố gắng thực hiện, và nếu đó là những gì bạn đang làm thì đó có thể là một ý tưởng hay.

Nếu bạn chỉ có một thứ thay đổi, nó quá mức cần thiết.

Các vấn đề liên quan