2009-03-04 8 views
12

Tôi đang đấu tranh để hiểu những gì lớp nhà máy của tôi nên làm trong dự án DDD của tôi. Có một nhà máy nên được sử dụng để tạo ra các đối tượng, nhưng chính xác nó nên làm gì. Hãy xem Lớp Nhà máy sau đây:Phương pháp nào nên đi vào lớp nhà máy DDD của tôi?

public class ProductFactory 
    { 
     private static IProductRepository _repository; 

     public static Product CreateProduct() 
     { 
      return new Product(); 
     } 

     public static Product CreateProduct() 
     { 
      //What else would go here? 
     } 

     public static Product GetProductById(int productId) 
     { 
      //Should i be making a direct call to the respoitory from here? 
      Greener.Domain.Product.Product p = _repository.GetProductById(productId); 
      return p; 
     } 
    } 

Tôi có nên thực hiện cuộc gọi trực tiếp đến kho lưu trữ từ trong nhà máy không?

Tôi nên quản lý việc tạo đối tượng khi lấy lại dữ liệu từ cơ sở dữ liệu như thế nào?

Tôi cần làm gì để hoàn thành lớp học này, tôi nên có phương pháp nào khác?

Tôi có nên sử dụng lớp này để tạo đối tượng Sản phẩm từ miền và kho lưu trữ từ phải không?

Vui lòng trợ giúp!

+1

Đừng đặt logic kho tại nhà máy của bạn. – mbillard

Trả lời

0

Trong ví dụ ở trên, tôi không rõ ràng về sự khác biệt giữa nhà máy và kho lưu trữ của bạn. Tôi tự hỏi nếu bạn không nên chỉ cần thêm CreateProduct như một phương thức vào kho lưu trữ, và sử dụng DI để đẩy kho lưu trữ vào mã cần nó? Nếu nhà máy không phải là làm bất cứ điều gì, vv ...

Hoặc nếu bạn chỉ muốn nó hoạt động như một kho lưu trữ đăng ký trên toàn thế giới, có lẽ cái gì đó như:

public static IFooRepository Default {get;private set;} 
public static void SetRepository(IFooRepository repository) { 
    Default = repository; 
} 

(trong tâm trí của tôi có vẻ như rõ ràng hơn để tách các "thiết lập" trong trường hợp này, nhưng bạn không cần phải đồng ý)

và có người gọi sử dụng var product = YourFactory.Default.CreateProduct(); vv

1

cá nhân tôi sẽ sử dụng các nhà máy ở vài trường hợp:

1) Cái gì đó ở nơi khác chi phối loại đối tượng mà nhà máy này trả về (ví dụ: nó có thể trả về các đối tượng tùy thuộc vào hoàn cảnh. Ví dụ trả về một đối tượng stub khi tôi đang thử nghiệm, trả về một thực thi thực tế khi tôi không (điều này rõ ràng là vấn đề Inversion of Control/Dependency Injection - nhưng nếu bạn không muốn thêm container vào dự án của bạn)).

2) Tôi có các đối tượng khá phức tạp có chứa, phụ thuộc, quan hệ khác vv và chúng cần phải được xây dựng cẩn thận để tránh tạo các tham chiếu vô nghĩa hoặc vô nghĩa. Ví dụ nếu tôi có một đối tượng Schedule tôi có thể cần một số trường bắt đầu, ngày kết thúc được đặt - nếu logic để truy xuất, tìm ra ngày này đủ phức tạp, tôi có thể không muốn lớp gọi điện biết về nó và chỉ gọi phương thức factory mặc định đã tạo đối tượng lịch biểu.

Hy vọng điều này sẽ hữu ích.

2

Điều gì sẽ xảy ra trong phương thức Tạo của nhà máy là bất kỳ điều gì là cần thiết để đặt một đối tượng mới đánh dấu thương hiệu vào trạng thái VALID.

Bây giờ, đối với một số đối tượng có nghĩa là bạn sẽ không làm bất cứ điều gì ngoại trừ này:

public Product Create() 
{ 
    return new Product(); 
} 

Tuy nhiên, bạn có thể có quy tắc kinh doanh, thiết lập mặc định, hoặc các yêu cầu khác mà bạn muốn thực thi khi một đối tượng là tạo. Trong trường hợp đó, bạn sẽ đặt logic đó vào phương thức đó.

Và đó là một phần lợi ích của Nhà máy.Bây giờ bạn có một và chỉ một nơi mà logic đặc biệt đó cư trú, và chỉ có một nơi mà một đối tượng mới được tạo ra.

11

Tôi có nên thực hiện cuộc gọi trực tiếp tới kho lưu trữ từ trong nhà máy không?

Không, không sử dụng nhà máy khi lấy đồ, chỉ sử dụng nhà máy khi bạn tạo lần đầu tiên.

Tôi nên quản lý việc tạo đối tượng khi lấy lại dữ liệu từ cơ sở dữ liệu bằng cách nào?

Chuyển dữ liệu đó vào nhà máy, nếu cần thiết cho việc tạo ban đầu của đối tượng.

Tôi cần làm gì để hoàn tất lớp học này , phương pháp nào khác tôi nên có?

Nhiều nhà máy thậm chí không phải là các lớp riêng lẻ, chúng chỉ là các phương pháp cung cấp tạo đối tượng. Bạn có thể gấp phương pháp nhà máy vào một lớp khác, nếu bạn cảm thấy như nó sẽ chỉ gọi một hàm tạo parameterless.

Tôi có nên sử dụng lớp này để tạo đối tượng Sản phẩm từ miền và kho từ phải không?

Kho lưu trữ dành cho việc tạo (tạo ý nghĩa) các đối tượng hiện có, nhà máy là lần đầu tiên bạn tạo đối tượng.

Ban đầu, nhiều nhà máy sẽ không làm gì nhiều ngoại trừ việc gọi một nhà xây dựng. Nhưng một khi bạn bắt đầu tái cấu trúc và/hoặc tạo phân cấp đối tượng lớn hơn, các nhà máy trở nên có liên quan hơn.

Giải thích và Ví dụ:

Ví dụ, trong dự án tôi đang làm việc trên tôi có một lớp cơ sở xử lý excel và nhiều lớp con thực hiện mà lớp cơ sở. Tôi sử dụng các nhà máy để có được một trong những thích hợp, và sau đó gọi phương pháp trên đó, không biết gì về phân lớp được trả lại. (Lưu ý: Tôi thay đổi một số tên biến và gutted/thay đổi rất nhiều mã)

Bộ xử lý cơ sở lớp:

public abstract class ExcelProcessor 
{ 
     public abstract Result Process(string ExcelFile); 
} 

Một trong những lớp con Processor:

public class CompanyAExcelProcessor : ExcelProcessor 
{ 
    public override Result Process(string ExcelFile) 
    { 
     //cool stuff 
    } 
} 

Factory:

public static ExcelProcessor CreateExcelProcessor(int CompanyId, int CurrentUserId) 
{ 
     CompanyEnum company = GetCompanyEnum(CompanyId); 
     switch (company) 
     { 
      case CompanyEnum.CompanyA: 
       return new CompanyAExcelProcessor(); 
      case CompanyEnum.CompanyB: 
       return new CompanyBExcelProcessor(); 
      case CompanyEnum.CompanyC: 
       return new CompanyCExcelProcessor(CurrentUserId); 
      //etc... 
     } 
} 

Cách sử dụng:

ExcelProcessor processor = CreateExcelProcessor(12, 34); 
processor.Process(); 
6

Hãy cẩn thận, có hai lý do để tạo một đối tượng mới: Tạo nó và bù nước nó từ cơ sở dữ liệu.

Trường hợp đầu tiên được nhà máy xử lý. Bạn có thể cung cấp một số phương pháp để tạo một đối tượng trên nhà máy. Các phương thức của nhà máy phải trả về các đối tượng hợp lệ, vì vậy bạn có thể chuyển các tham số cho các phương thức này để cung cấp thông tin được yêu cầu.

Phương pháp nhà máy cũng có thể chọn loại thực tế để khởi tạo dựa trên thông số.

Bạn không nên trộn lẫn với việc bù nước từ cơ sở dữ liệu. Loại instantiation này sẽ lấy các giá trị từ datarow và khởi tạo đối tượng với nó. Tôi thường gọi đây là số trình tạo dữ liệu thay vì nhà máy .

Sự khác biệt chính là nhà máy sẽ khởi tạo một đối tượng có nhận dạng mới trong khi nhà xây dựng dữ liệu sẽ khởi tạo một đối tượng có nhận dạng đã tồn tại.

+3

Nhà máy là bình thường trong miền trong khi trình tạo dữ liệu nằm trong cơ sở hạ tầng kiên trì. – thinkbeforecoding

0

@ThinkBeforeCoding - trong ví dụ @ m4bwav, nhà máy đang nhận được ID hợp lệ từ phương thức trợ giúp, nhưng nó không tạo bản ghi mới trong lớp kiên trì ở bất kỳ đâu. Tuy nhiên, nếu tôi đang sử dụng cột nhận dạng tự động do cơ sở dữ liệu tạo làm danh tính của tôi, có vẻ như một nhà máy sẽ phải gọi vào kho lưu trữ để thực hiện tạo đối tượng ban đầu. Bạn có thể nhận xét về phương pháp nào là "chính xác" không?

0

Trong xây dựng bạn có thể có bất kỳ logic bạn cần phải inforce các bất biến trên entites của bạn, một ví dụ nhỏ sử dụng Java là ngôn ngữ phát triển ...

Tôi có một thực thể tài khoản đó có một tên người dùng, mật khẩu và email, tất cả các thuộc tính cần thiết vì vậy tôi có:

public class User { 

private String username; 
private String password; 
private String email: 

/** 
* @throws IllegalArgumentException if the username is null, the password is null or the 
* email is null. 
*/ 
public User(final String theUsername, final String thePassword, final String theEmail) { 
Validate.notNull(theUsername); 
Validate.notNull(thePassword); 
Validate.notNull(theEmail); 

this.username = theUsername; 
this.password = thePassword; 
this.email = theEmail; 
} 

// Getters/Setters/equal/hashCode/toString 
} 

và sau đó tôi có UserBuilder:

public class UserBuilder { 
private String username; 
private String password; 
private String email; 

public UserBuilder withUsername(final String theUsername) { 
Validate.notNull(theUsername); 

this.username = theUsername; 

return this; 
} 

public UserBuilder withPassword(final String thePassword) { 
Validate.notNull(thePassword); 

this.password = thePassword; 

return this; 
} 

public UserBuilder withEmail(final String theEmail) { 
Validate.notNull(theEmail); 

this.email = theEmail; 

return this; 
} 

public User build() { 
User user = new User(this.username, this.password, this.email); 

return user; 
} 
}; 

và bạn có thể sử dụng xây dựng như thế này :

UserBuilder builder = new UserBuilder(); 

try { 
User user = builder.withUsername("pmviva").withPassword("My Nifty Password").withEmail("[email protected]").build(); 
} catch (IllegalArgument exception) { 
    // Tried to create the user with invalid arguments 
} 

Mục đích duy nhất của nhà máy là tạo ra các đối tượng hợp lệ. Để không lặp lại mã tạo và mã hydrat, bạn có thể có kho lưu trữ của bạn để truy vấn một rowset từ cơ sở dữ liệu và ủy quyền tạo đối tượng cho một người xây dựng thông qua dữ liệu của rowset.

Hope this helps

Cảm ơn Pablo