Liệu mô hình nhà máy trừu tượng có quy mô?


8

Tôi vẫn đang cố gắng để hiểu các mẫu thiết kế ở đây, sau khi tìm hiểu mẫu Nhà máy trừu tượng, tôi nhận ra rằng mẫu này sẽ không có quy mô tốt. Hãy nhìn vào sơ đồ uml của mẫu nhà máy trừu tượng

sơ đồ uml

Nếu tôi phải tạo một 'Tóm tắt sản phẩm' mới, tôi sẽ phải thêm một phương thức trừu tượng 'Tạo sản phẩm' trong 'Tóm tắt', có tác dụng thực hiện cả ConcreateFactory1, ConcreateFactory2.

Câu hỏi của tôi ở đây là, liệu mô hình của Nhà máy Trừu tượng có quy mô nào không (hoặc) Tôi đang nghĩ sai hướng ở đây?

cảm ơn trước


Tôi nghĩ rằng sơ đồ bạn trình bày, trông tương đối chuẩn, đã được đơn giản hóa để minh họa mô hình trong câu hỏi. Tuy nhiên, nếu bạn cần một cái gì đó phức tạp hơn, bạn luôn có thể định nghĩa AbstractFactory chỉ bằng một phương thức: Tạo sản phẩm (ProductType) và sau đó có một nhà máy trong một nhà máy sẽ xem xét loại và khởi tạo lớp cụ thể dựa trên đó.
DXM

@DXM Điều đó không khắc phục được sự cố. Bạn vẫn sẽ cần phải thay đổi việc thực hiện các nhà máy bê tông mỗi khi bạn thêm sản phẩm mới.
Euphoric

Chà, điều duy nhất có thể mở rộng là giao diện trừu tượng thực tế, nhưng vâng, nếu bạn có N sản phẩm và cách tạo M, cho dù bạn cắt nó như thế nào, bạn cần triển khai N x M, trừ khi bạn đi với một chiến lược hoàn toàn khác .
DXM

@Euphoric: Không nhất thiết. Bạn chỉ cần thêm một lớp nhà máy và đăng ký nó với nhà máy trừu tượng. Có thể hơi khó chịu, nhưng để nhân rộng và SRP tôi thấy việc thêm một chút rắc rối hơn là thay đổi.
Marjan Venema

@MarjanVenema Bây giờ câu hỏi là nếu nó thực sự là một nhà máy và không phải là mô hình khác nhau.
Euphoric

Câu trả lời:


5

Tóm tắt Nhà máy quy mô tốt.

Có một nguyên tắc cơ bản quy định rằng một lớp nên làm tốt một việc. Vấn đề của bạn ở đây là bạn đang cố gắng làm cho nhiều lớp làm nhiều việc.

Bạn không cần phải gắn bó với một nhà máy trừu tượng. Bạn có thể (và nên có) một số:

AbstractProductAFactoryđịnh nghĩa giao diện để sản xuất ProductA. Việc triển khai cụ thể của bạn (Concrete ProducttAFactory1, Concrete ProducttAFactory2) sẽ mở rộng nó.

AbstractProductBFactoryđịnh nghĩa giao diện để sản xuất ProductB. Việc triển khai cụ thể của bạn ( ConcreteProductBFactory1, ConcreteProductBFactory2) sẽ mở rộng nó.

Nếu sau đó bạn cần một ProductC, hãy tạo một cái mới AbstractProductCFactory. Không cần phải thay đổi bất kỳ nhà máy khác của bạn theo cách này.

CẬP NHẬT Lý tưởng nhất là ProductA nên đại diện cho một loại sản phẩm - nghĩa là tất cả các sản phẩm có chung giao diện mà bạn đang gọi ProductA. Trong các bình luận tôi đề nghị rằng đây là một cái gì đó giống như Pizza:

interface AbstractPizzaFactory {
    public Pizza buildPizza(List<Topping> toppings);
}


class ThinCrustPizzaFactory implements AbstractPizzaFactory {
    public Pizza buildPizza(List<Topping> toppings){

        ...

    }
}

class DeepDishPizzaFactory implements AbstractPizzaFactory {
    public Pizza buildPizza(List<Topping> toppings){

        ...

    }
}

Và như thế. Việc thêm PanPizzaFactory sẽ không ảnh hưởng đến bất kỳ lớp nào khác - đó chỉ là một triển khai cụ thể mới của PizzaFactory. Nếu bạn có các sản phẩm không phải là pizza - ví dụ như bánh sandwich, đó là nơi bạn tạo ra một nhà máy trừu tượng khác (ví dụ AbstractSandwichFactory:).

Vấn đề thực sự là, bạn sẽ không muốn có một nhà máy trừu tượng xây dựng hai loại sản phẩm rất khác nhau với hai phương pháp "xây dựng" khác nhau. Nhóm chúng một cách hợp lý như bạn có thể để chúng chia sẻ một giao diện, và sau đó tạo một nhà máy trừu tượng xác định cách các nhà máy cụ thể nên xây dựng các triển khai của giao diện đó.


4
Bạn đang đùa, phải không? Nếu công ty của bạn làm 256 sản phẩm thì sao? Hay 1024?
Robert Harvey

@RobertHarvey - Tôi giả sử rằng ProductA là một nhóm sản phẩm - giả sử đó là một AbstractPizzaFactory. Điều này có thể có một ThinCrustPizzaFactory cụ thể, một PanPizzaFactory cụ thể và một DeepDishPizzaFactory cụ thể. Tương tự như vậy, bánh sandwich sẽ được xây dựng bởi các kiểu con của AbstractSandwichFactory. Điều này khác với và AgraugeFactory với cả phương thức buildPizza và buildSandwich.
Matthew Flynn

@RobertHarvey - Trong khi đó, các biến thể tinh tế trong các sản phẩm (như toppings) có thể là một cái gì đó có thể được xử lý riêng biệt. Có lẽ phương pháp nhà máy của bạn sẽ được AbstractPizzaFactory.buildPizza(List<Topping> toppings).
Matthew Flynn

Bạn có thể muốn làm cho những điều đó rõ ràng trong câu trả lời của bạn.
Robert Harvey

@RobertHarvey - cập nhật
Matthew Flynn

4

Vấn đề với nhân rộng là mã có thể mở rộng theo nhiều cách khác nhau. Vấn đề bạn đang gặp phải đơn giản là do cần phải mở rộng theo một hướng, mẫu thiết kế đó không dành cho. Trong trường hợp mô hình Nhà máy trừu tượng, nó có nghĩa là mở rộng quy mô theo cách thêm các nhà máy bê tông mới, nhưng việc thêm sản phẩm mới gây ra những thay đổi lớn về cấu trúc.

Một trong những điểm của thiết kế và kiến ​​trúc phần mềm là xác định các hướng có khả năng nhất mà mã sẽ chia tỷ lệ và chọn các mẫu dựa trên các hướng có khả năng đó. Nếu bạn xác định, việc thêm sản phẩm mới có nhiều khả năng hơn là thêm nhà máy bê tông mới, thì sử dụng Tóm tắt Nhà máy không phải là một ý tưởng hay và tốt hơn là nên nghĩ lại hoàn toàn về thiết kế.


1
câu trả lời của bạn có ý nghĩa hơn so với câu hỏi cứng nhắc "TÓM TẮT NHÀ MÁY QUẢNG CÁO!" của anh chàng kia ...
Thổ Nhĩ Kỳ

@Euphoric, như bạn đang đề xuất, Tóm tắt mô hình nhà máy theo cách thêm các nhà máy bê tông mới, nhưng cuối cùng nhà máy bê tông mới phải tạo ra các sản phẩm, tạo ra sản phẩm và cuối cùng chúng ta nên thay đổi cấu trúc, không phải vậy đúng?
Jitendar

@Jitendar Tôi không hiểu ý bạn. Quan điểm của nhà máy trừu tượng là có một nhóm trừu tượng tương đối ổn định (ProductA, ProductB) và các nhà máy bê tông tạo ra các triển khai của những trừu tượng đó, điều đó cũng có liên quan bằng cách nào đó. Nếu khả năng thêm trừu tượng mới cao hơn so với việc thêm các triển khai cụ thể mới của các trừu tượng đó, thì sử dụng Tóm tắt Factory không phải là một lựa chọn tốt.
Euphoric

3

Vâng, bạn đã đúng, "nhà máy trừu tượng" không có quy mô tốt khi bạn cần thêm các sản phẩm trừu tượng .

Nhưng trong rất nhiều tình huống trong thế giới thực, bạn có số lượng sản phẩm thay đổi, nhưng chỉ có một số lượng nhỏ các sản phẩm trừu tượng cố định để hỗ trợ. Ví dụ, lấy ví dụ về các widget GUI từ bài viết trên wikipedia về các nhà máy trừu tượng . Nhà máy GUI trừu tượng có thể có một phương thức createWidget(thay vì createButton), trong đó Widgetlà "sản phẩm trừu tượng", tạo ra lớp cơ sở trên cùng cho một họ gồm vài chục thành phần GUI. Việc thêm các widget GUI mới không có nghĩa là thay đổi giao diện của nhà máy trừu tượng, vì vậy không có giao diện nào của nhà máy cụ thể phải thay đổi.

Có nhiều sản phẩm trừu tượng có nghĩa là bạn sẽ có rất nhiều hệ thống phân cấp lớp khác nhau trong mã của bạn. Và nếu đó là trường hợp, bạn có thể xem xét để tạo một nhà máy riêng (hoặc nhà máy trừu tượng) cho mỗi phân cấp.


0

Yếu tố mở rộng của bạn là một vấn đề đơn giản của quản lý phụ thuộc. Một lớp càng có nhiều phụ thuộc - API càng ổn định và chu đáo.

Không có vấn đề trong việc tạo ra một nhà máy được xác định bởi trách nhiệm tạo ra các loại có tính chất tương tự hoặc gắn kết. Nhưng càng có nhiều lớp phụ thuộc vào nhà máy này - sự gắn kết này càng nghiêm ngặt.

(Lưu ý: điều này có thể được thực hiện theo cách dần dần, không nhất thiết phải bằng một BDUF)

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.