2009-10-16 5 views
9

lá trong hỗn hợp thực hiện Hợp phần có phương thức Thêm loại bỏ và GetChild mà anh ta sẽ không bao giờ sử dụng (vi phạm phân tách Giao diện)SOLID có phải là mẫu tổng hợp không?

do đó việc sử dụng mẫu tổng hợp SOLID?

liên kết đến composit http://www.dofactory.com/Patterns/PatternComposite.aspx

+0

Câu hỏi của bạn chưa rõ ràng. Ngoài ra, những gì bạn có nghĩa là "SOLID" – monksy

+0

Tôi đã thêm một liên kết SOLID cho người hỏi, ở trên. – SingleShot

+0

SRP và LSP cũng bị vi phạm cùng với ISP. Vì vậy, SOLID nguy hiểm. :) – Narek

Trả lời

10

Mùi thực sự trong mô hình như mô tả trong liên kết của bạn và hầu hết các sách là Component có các phương pháp của một Composite. Tôi nghĩ rằng điều này có lẽ là do mô hình khá cũ và đã được lặp đi lặp lại theo cách đó trong nhiều năm. Việc tôi lấy là chỉ có Composite nên có bất kỳ phương pháp nào liên quan đến việc tổng hợp.

Tôi đã từng chuyển đổi trò chơi trên bảng thành trò chơi trên máy tính. Các mảnh ghép được đặt trên bản đồ trái đất, chia thành các hình lục giác. 99% của tất cả các hình lục giác đại diện cho một vị trí duy nhất. Thật không may, một vài trong số các hình lục giác chứa nhiều vị trí, ví dụ, một số có một vài hòn đảo bên trong chúng. Tôi đã sử dụng mẫu tổng hợp để thể hiện các vị trí này, nhưng không được mô tả trên liên kết của bạn. Đó là một cái gì đó như thế này (trong Java):

public interface Location { 
    Set<Army> getArmies(); 
} 

public class SingleLocation implements Location { 

    public Set<Army> getArmies() { 
     return armies ; 
    } 

    private Set<Army> armies = new HashSet<Army>(); 
} 

public class CompositeLocation implements Location { 

    public Set<Army> getArmies() { 

     Set<Army> armies = new HashSet<Army>(); 

     for(Location subLocation: subLocations) { 
     armies.addAll(subLocation.getArmies()); 
     } 

     return armies; 
    } 

    public void addSubLocation(Location location) { 
     subLocations.add(location); 
    } 

    private Set<Location> subLocations = new HashSet<Location>(); 
} 

Lưu ý rằng chỉ có Composite có phương pháp hợp lại, và thậm chí không tiếp xúc với thực tế là nó có con với hầu hết các khách hàng (trong ví dụ này, khách hàng chỉ muốn danh sách quân đội từ một địa điểm - thực tế là họ ở nhiều địa điểm phụ không liên quan).

Hãy nhớ rằng các mẫu thiết kế không phải là những thứ đặt sẵn trong đá mà bạn phải thực hiện chính xác. Hãy nghĩ về chúng như là công thức nấu ăn. Khi bạn làm theo một công thức nấu ăn trong khi nấu ăn, bạn chắc chắn có thể chỉ cần làm theo nó một cách chính xác. Tuy nhiên, một số đầu bếp sẽ ném vào xoắn riêng của họ vào công thức. Những người khác thậm chí sẽ không nhìn vào nó bởi vì họ là các chuyên gia và có thể ném một cái gì đó với nhau trong tinh thần của công thức mà không hề nghĩ về nó. Cũng vậy với các mẫu thiết kế. Họ là công thức nấu ăn dễ uốn.

Bạn cũng có thể thực hiện các nguyên tắc RẮN đó quá xa. Nếu bạn đọc các bài báo của Robert Martin, ông tuyên bố rằng việc áp dụng các nguyên tắc trên bảng mà không có ý nghĩ nào sẽ mang lại mã quá phức tạp. Phần mềm được thiết kế thông qua một loạt các sự cân bằng và cân bằng - đôi khi bạn từ bỏ RẮN thuần túy vì nó mang lại mã ít phức tạp hơn. Nếu bạn đã làm cho mã của bạn được đóng gói hoàn hảo, linh hoạt, tách rời, v.v., bạn sẽ phát minh ra một ngôn ngữ lập trình mới :-)

+0

Điều này rất phổ biến, vì những lý do chính đáng - nhưng có những lý do cho phiên bản chuẩn. Ví dụ, các mục có thể có các phụ thuộc chức năng với nhau bên cạnh sự tổng hợp đơn giản - chiều cao của một đoạn, ví dụ, phụ thuộc vào chiều cao của mỗi dòng văn bản, phụ thuộc vào chiều cao của mỗi ký tự trong dòng. Sử dụng một băm riêng biệt có nghĩa là các vật phẩm tổng hợp phải tham khảo lại hỗn hợp để tìm người thân trực tiếp của chúng. Tất nhiên, điều này cũng có lợi thế - và tổng hợp có thể chịu trách nhiệm về tóm tắt subtree như chiều cao đoạn đó. – Steve314

5

Tôi có thể nói rằng mẫu Composite như được mô tả trong liên kết của bạn vi phạm Liskov substitution principle, một trong năm nguyên tắc SOLID.

Component có các phương thức chỉ có ý nghĩa đối với một số Composite ví dụ: Add(). Leaf được kế thừa từ Component để nó sẽ có phương thức Add() giống như bất kỳ phương thức nào khác Component. Nhưng Leafs không có con, vì vậy các cuộc gọi phương pháp sau đây không thể trả về một kết quả có ý nghĩa:

myLeaf.Add(someChild);

cuộc gọi đó sẽ phải ném một MethodNotSupportedException, trở null hoặc chỉ rõ trong một số cách khác để người gọi rằng việc thêm một đứa trẻ đến một số Leaf không có ý nghĩa.

Vì vậy, bạn không thể xử lý số Leaf như bất kỳ Component nào khác vì bạn sẽ nhận được ngoại lệ nếu bạn cố gắng.Liskov bang nguyên tắc substition:

Hãy q (x) là một tài sản chứng minh về đối tượng x kiểu T. Sau đó q (y) nên là đúng cho các đối tượng y kiểu S nơi S là một subtype của T.

Components có thuộc tính mà bạn có thể thêm trẻ em vào chúng. Nhưng bạn không thể thêm trẻ em vào số Leaf, mặc dù Leaf là một loại phụ của Component, vi phạm nguyên tắc.

+0

Một loại phải đi chệch khỏi khả năng tương tác ngữ nghĩa với loại cha mẹ của nó để đủ điều kiện là vi phạm Nguyên tắc thay thế Liskov, vì vậy nếu loại lá làm như vậy thì nó sẽ là do không có khả năng gọi Add() với một đứa trẻ và sau đó gọi GetChild() với chỉ mục dự kiến. Tuy nhiên, hành vi bỏ qua hoàn toàn sẽ không đủ điều kiện là vi phạm. Phương thức Add() không có hợp đồng ngầm hoặc rõ ràng đòi hỏi nó cung cấp phản hồi rằng đứa trẻ được thêm vào, nhưng có một hợp đồng tiềm ẩn giả định một đứa trẻ được thêm vào có thể được lấy bởi phương thức GetChild(). –

+0

BTW, lý do mẫu đối tượng Null có hiệu quả là vì nó bỏ qua hành vi trong khi vẫn duy trì khả năng tương tác ngữ nghĩa. –

0

Sử dụng Composite cho phép bạn xử lý tất cả các đối tượng một cách thống nhất và có thể để loại bỏ "instanceOf" là dấu hiệu rõ ràng của một mùi mã. Vì vậy, nó là tôn trọng LSP (Liskov's) ở cái nhìn đầu tiên. Tuy nhiên, khi bạn phân biệt việc triển khai phương pháp phổ biến, có khả năng nó sẽ bắt đầu vi phạm LSP. Vì vậy, IMO, chúng ta cần giữ sự cân bằng đó.