Đây có phải là một mẫu thiết kế hợp lệ hay không?


37

Một mẫu phổ biến mà tôi thấy là mẫu được gọi là Mappermẫu (không bị nhầm lẫn với mẫu DataMapperhoàn toàn khác), dùng làm đối số của một loại nguồn dữ liệu "thô" (ví dụ: ADO.NET DataReaderhoặc DataSet) và ánh xạ các trường tới thuộc tính trên một đối tượng kinh doanh / tên miền. Thí dụ:

class PersonMapper
{
    public Person Map(DataSet ds)
    {
        Person p = new Person();
        p.FirstName = ds.Tables[0].Rows[0]["FirstName"].ToString();
        // other properties...
        return p;
    }
}

Ý tưởng là Cổng / DAO / Kho lưu trữ của bạn / v.v. sẽ gọi vào Mapper trước khi nó trả về, do đó bạn có được một đối tượng kinh doanh phong phú so với vùng chứa dữ liệu cơ bản.

Tuy nhiên, điều này dường như có liên quan, nếu không giống hệt với mẫu Factory (theo cách nói của DDD, dù sao), nó xây dựng và trả về một đối tượng miền. Wikipedia nói lại điều này: Nhà máy DDD:

Factory: các phương thức tạo đối tượng miền nên ủy quyền cho một đối tượng Factory chuyên biệt sao cho việc triển khai thay thế có thể dễ dàng thay thế cho nhau.

Từ trích dẫn đó, điểm khác biệt duy nhất tôi có thể nghĩ là Nhà máy kiểu DDD có thể được tham số hóa để có thể trả về một loại đối tượng chuyên biệt nếu nhu cầu nảy sinh (ví dụ: BusinessCustomer so với ResidCustomer) trong khi "Mapper" được khóa vào một lớp cụ thể và chỉ dịch.

Vì vậy, có sự khác biệt giữa hai mẫu này hay về cơ bản chúng là cùng một thứ với các tên khác nhau?


Điều này có khác với ORM không và nếu có thì sự khác biệt nằm ở đâu?
JB King

Các ORM tự động xử lý ánh xạ cho bạn - điều này phù hợp hơn với kịch bản mà bạn không thể sử dụng ORM (hoặc phải viết lớp dữ liệu của riêng bạn / ORM mỏng)
Wayne Molina

1
Tôi thực sự vật lộn để xem DataMapper là "thứ gì đó hoàn toàn khác".
pdr

Có lẽ tôi đã nhầm - Tôi nghĩ rằng DataMappermô hình đã tự truy cập cơ sở dữ liệu, trong khi "Mapper" này không lấy từ cơ sở dữ liệu, chỉ chuyển đổi một tập kết quả của một loại nào đó thành một đối tượng.
Wayne Molina

martinfowler.com/eaaCatalog/dataMapper.html Tôi sắp xếp xem bạn muốn nói gì, nhưng đọc đoạn cuối đó, điều đó đúng. Nhìn vào danh mục PEAA. martinfowler.com/eaaCatalog/index.html . Những gì bạn đang mô tả chắc chắn là một loại Mapper và phù hợp hơn với DataMapper so với phần còn lại.
pdr

Câu trả lời:


23

Mặc dù đây là lần đầu tiên tôi nghe thấy mẫu Mapper, nhưng đối với tôi nghe có vẻ giống mẫu Builder hơn là Factory.

Trong mẫu Factory, bạn gói gọn logic để tạo các đối tượng của một số lớp liên quan. Ví dụ điển hình sẽ là một tình huống trong đó bạn cần tạo một đối tượng của một lớp con cụ thể của một số lớp cơ sở trừu tượng tùy thuộc vào một số tham số. Vì vậy, Factory luôn trả về một con trỏ hoặc một tham chiếu đến lớp cơ sở, nhưng nó thực sự tạo ra một đối tượng của lớp dẫn xuất thích hợp dựa trên các tham số bạn đưa ra.

Ngược lại, một lớp Builder luôn tạo các đối tượng của cùng một lớp. Bạn sẽ sử dụng nó nếu việc tạo một đối tượng phức tạp, ví dụ: hàm tạo của nó có nhiều đối số, không phải tất cả trong số đó có thể có sẵn ngay lập tức. Vì vậy, một đối tượng của trình xây dựng có thể là nơi lưu trữ các giá trị cho các đối số của hàm tạo cho đến khi bạn có tất cả và sẵn sàng tạo "sản phẩm" hoặc nó có thể cung cấp các giá trị mặc định hợp lý và cho phép bạn chỉ định các đối số có giá trị bạn cần thay đổi. Một trường hợp sử dụng điển hình cho mẫu Builder là để tạo các đối tượng bạn có thể cần trong một bài kiểm tra đơn vị, để tránh làm lộn xộn mã kiểm tra với tất cả logic tạo.

Đối với tôi, Mapper nghe giống như một biến thể của Builder, trong đó các tham số của hàm tạo có ở dạng bản ghi cơ sở dữ liệu hoặc một số cấu trúc dữ liệu "thô" khác.


Hmm, tôi đã nghe nói về Builder nhưng không biết 100% về những gì nó đòi hỏi - điều này đã giúp làm sáng tỏ mọi thứ! Có vẻ như sự khác biệt lớn là Factory trả về một lớp giao diện / lớp trừu tượng thực sự là một lớp cụ thể dựa trên các tham số (nếu có ý nghĩa) trong khi Builder / Mapper lấy dữ liệu thực tế và ánh xạ chúng tới các thuộc tính, mà không có logic (nếu có) ?
Wayne Molina

1
@Waine M: khá nhiều. Mặc dù có thể có rất nhiều logic trong Trình tạo, bởi vì ánh xạ dữ liệu tới các thuộc tính có thể hoàn toàn không đơn giản. Trong thực tế, một trình xây dựng có thể chứa các trình xây dựng khác để xây dựng các tham số. :)
Dima

5
Mẫu Builder cho phép bạn đặt tất cả thông tin cần thiết để xây dựng một đối tượng phức tạp (thường là bất biến) theo thời gian và sau đó khởi tạo đối tượng ở cuối quá trình. Đó không phải là những gì đang xảy ra ở đây.
pdr

+1 Đồng ý rằng đây là một cách tiếp cận hợp lý, có lớp 'người lập bản đồ' riêng biệt để đóng vai trò trung gian hòa giải giữa các đối tượng DTO và các đối tượng mô hình miền. Nó cũng có ích khi các đối tượng mô hình miền cần được đưa vào một số trạng thái đặc biệt khi được xây dựng (tức là giao diện .NET ISupportInitialize).
MattDavey

@pdr, tôi đồng ý rằng Mapper không chính xác như người xây dựng, vì tất cả dữ liệu đều có sẵn cùng một lúc. Nhưng nó rất giống nhau, vì nó chỉ xây dựng một loại đối tượng.
Dima

8

Điểm chung duy nhất về Mapper, Builder và Factory là họ cung cấp một "sản phẩm được xây dựng" - và đối tượng của một loại. Để tránh bất kỳ sự nhầm lẫn, tôi đang đề cập đến các cuộc thảo luận sau cho định nghĩa tương ứng của họ.

  1. Mapper - gần với những gì được giải thích ở đây: http://www.codeproject.com/KB/l Library / AutoMapper.aspx . Điều này không chính xác như trên - nhưng gần nhất tôi tìm thấy về mapper.

  2. Trình tạo - như được xác định tại đây: http://www.oodesign.com/builder-potype.html

  3. Nhà máy - được xác định tại đây: http://www.oodesign.com/factory-potype.html

Mapper thực chất là một constructor từ trong ra ngoài. Giả sử trong một thời gian, nếu bạn không có trình ánh xạ - Khi bạn cần nhiều bộ tham số thì tất cả đều là đối số trên hàm tạo. Bây giờ khi mọi thứ phát triển, một số ứng dụng không nhận thức được các thuộc tính bổ sung cần đi theo hàm tạo trong đó một trong hai tính toán hoặc sử dụng mặc định. Điều quan trọng là mapper có thể làm điều này cho bạn - và sẽ hữu ích hơn nếu điều này có liên kết với các đối tượng bên ngoài để quyết định một thuật toán như vậy để xây dựng.

Builder rất khác với mapper. Một trình xây dựng là điều cần thiết khi một đối tượng hoàn chỉnh được cấu tạo bằng nhiều phần của đối tượng. Đó là kiểu lắp ráp các vật thể bằng cách ghép nhiều bộ phận lại với nhau. Ngay cả việc khởi tạo các đối tượng bộ phận riêng lẻ cũng liên quan đến sự tồn tại của các bộ phận khác.

Các mẫu nhà máy trông rất đơn giản ngay từ đầu. Nó trả về một đối tượng mới được xây dựng. Nếu bất kỳ hàm tạo thông thường nào có thể cung cấp cho tôi một cá thể đầy đủ chức năng bằng cách sử dụng một toán tử như new ()? Tại sao tôi cần một nhà máy cho tôi kết quả tương tự?

Tuy nhiên, việc sử dụng mô hình nhà máy thường rất cụ thể; mặc dù thường xuyên nhất, không được hiển thị trong văn học, nơi điều này được áp dụng. Thông thường, một ứng dụng tạo ra một nhà máy được chia sẻ cho các đối tượng khác nhau, những người cần tạo các đối tượng sản phẩm đó trong quá trình thực thi. Khi nhiều sản phẩm như vậy được tạo, phương thức Factory cho phép tạo các đối tượng dựa trên chính sách nhất định , chẳng hạn, người ta có thể buộc một mẫu nhất định được sử dụng bởi phương thức Factory khi tất cả các đối tượng được tạo. Đây không giống như một phương pháp xây dựng; ở đây sản phẩm ra chỉ có một (và độc lập). Điều này cũng không giống như mapper; ở đây dữ liệu ngoài được thiết lập để tạo đối tượng theo máy khách thực sự là tối thiểu. Mẫu nhà máy thực sự cung cấp (như tên cho thấy) một đối tượng sản phẩm tương tự nhất quán!

Dipan.



4

Khi tôi xem qua các câu trả lời, tôi thấy tất cả những người trả lời đều cung cấp các câu trả lời sai về mặt ngữ nghĩa. Tôi nghĩ điều này là do tất cả các bạn quá tập trung vào câu hỏi, trong đó tập trung vào việc mapper có liên quan đến nhà máy hoặc nhà xây dựng.

Trong thực tế, Mapper không giống với nhà máy hoặc nhà xây dựng. Mapper giống như mẫu bộ điều hợp (sử dụng cách nói GoF). Mẫu bộ điều hợp cung cấp chức năng để chuyển đổi một đại diện này sang một đại diện khác. OP đã đề cập đến Bộ dữ liệu và Trình ghi dữ liệu trong ADO.NET-- làm thế nào về SqlDataAd CHƯƠNG? Câu trả lời là trong tên. Mapper là một tên mới cho một thứ mà các lập trình viên lớn tuổi đã biết đến từ lâu: bộ điều hợp.

Mapper chuyển đổi một đại diện thành một đại diện khác - chính là định nghĩa của mẫu bộ điều hợp.


1

Những gì bạn đang làm ở đây thực sự là một loại chuyển đổi loại (bạn chuyển đổi dữ liệu thô của mình thành đối tượng kinh doanh). Bạn có thể sử dụng Mẫu nhà máy để thực hiện chính xác (nghĩa là chuyển đổi loại), vì vậy, theo một cách nào đó, lớp của bạn là một nhà máy (mặc dù tôi sẽ sử dụng Nhà máy tĩnh cho việc đó).


0

Các nhà xây dựng gói gọn logic kinh doanh phức tạp để xây dựng một đối tượng. Mặt khác, Mapper chỉ nên sao chép các trường từ cái này sang cái khác.

Ví dụ ánh xạ từ Đối tượng nhân viên cơ sở dữ liệu sang Đối tượng nhân viên miền, ánh xạ từ Đối tượng nhân viên miền sang Hợp đồng khách hàng.

Các nhà xây dựng mặt khác lưu trữ nhiều quyết định kinh doanh để xây dựng một đối tượng. Từ quan điểm Trách nhiệm duy nhất, điều này có ý nghĩa.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.