2016-05-30 17 views
5

Tôi khá mới với các mẫu và tôi đang nghiên cứu Mẫu trang trí cho một chương trình tôi phải viết.Thiết kế mẫu trang trí

Nghiên cứu trên mạng, tôi thấy một ví dụ về mẫu Decorator (nó là Java pseudo-code):

class Solution1 
{ 
    static interface Component 
    { 
     void doStuff(); 
    } 

    static class MyComponent implements Component 
    { 
     public void doStuff() 
     { 
      // ... 
     } 
    } 

    static class ComponentDecorator implements Component // This is the Decorator pattern. 
    { 
     private final Component component; 

     public ComponentDecorator(Component component) 
     { 
      this.component = component; 
     } 

     public void doStuff() 
     { 
      this.component.doStuff(); 
     } 
    } 

    static class ComponentDecorator1 extends ComponentDecorator 
    { 
     public ComponentDecorator1(Component component) 
     { 
      super(component); 
     } 

     private void doExtraStuff1() 
     { 
      // ... 
     } 

     public void doStuff() 
     { 
      super.doStuff(); 
      doExtraStuff1(); 
     } 
    } 

    static class ComponentDecorator2 extends ComponentDecorator 
    { 
     public ComponentDecorator2(Component component) 
     { 
      super(component); 
     } 

     private void doExtraStuff2() 
     { 
      // ... 
     } 

     public void doStuff() 
     { 
      super.doStuff(); 
      doExtraStuff2(); 
     } 
    } 

    public static void main(String[] args) 
    { 
     MyComponent   c = new MyComponent(); 
     ComponentDecorator1 cd1 = new ComponentDecorator1(c); 
     ComponentDecorator2 cd2 = new ComponentDecorator2(cd1); 

     cd2.doStuff(); // Executes Component.doStuff, ComponentDecorator1.doExtraStuff1, ComponentDecorator2.doExtraStuff2 
    } 
}; 

Khi tôi phân tích ví dụ này, tôi nhận ra rằng trong quá khứ tôi đã làm một mô hình rất giống nhau nhưng theo cách khác nhau:

import java.util.*; 

class Solution2 
{ 
    static interface Component 
    { 
     void doStuff(); 
    } 

    static class MyComponent implements Component 
    { 
     public void doStuff() 
     { 
      // ... 
     } 
    } 

    static class ComponentDecorator implements Component // This is NOT the Decorator pattern! 
    { 
     private final List<Component> components = new ArrayList<Component>(); 

     public ComponentDecorator() 
     { 
     } 

     public ComponentDecorator addComponent(Component component) 
     { 
      this.components.add(component); 
      return this; 
     } 

     public void removeComponent(Component component) // Can Decorator do this? 
     { 
      // ... 
     } 

     public void doStuff() 
     { 
      for(Component c : this.components) c.doStuff(); 
     } 
    } 

    static class ComponentDecorator1 implements Component 
    { 
     public ComponentDecorator1() 
     { 
     } 

     private void doExtraStuff1() 
     { 
      // ... 
     } 

     public void doStuff() 
     { 
      doExtraStuff1(); 
     } 
    } 

    static class ComponentDecorator2 implements Component 
    { 
     public ComponentDecorator2() 
     { 
     } 

     private void doExtraStuff2() 
     { 
      // ... 
     } 

     public void doStuff() 
     { 
      doExtraStuff2(); 
     } 
    } 

    public static void main(String[] args) 
    { 
     ComponentDecorator cd = new ComponentDecorator(); 
     cd.addComponent(new MyComponent()); 
     cd.addComponent(new ComponentDecorator1()); 
     cd.addComponent(new ComponentDecorator2()); 

     cd.doStuff(); // Executes MyComponent.doStuff, ComponentDecorator1.doExtraStuff1, ComponentDecorator2.doExtraStuff2 
    } 
} 

theo tôi, ví dụ thứ hai có thể được sử dụng trong cùng một tình huống mà một mẫu trang trí có thể được sử dụng, nhưng nó linh hoạt hơn (bạn có thể, bởi ví dụ, loại bỏ hoặc sắp xếp lại các thành phần trong danh sách), vì vậy câu hỏi của tôi:

  • Giải pháp 1 (Mẫu trang trí chính xác) có tốt hơn giải pháp 2 không? Tại sao?
  • Có thể thêm các chức năng để xóa các phiên bản trong giải pháp 1 không?
  • Có thể thêm các chức năng để sắp xếp lại các thể hiện trong giải pháp 1 không?
+0

nó là không thể nói đó là tốt hơn bởi vì họ làm những việc khác nhau. –

+0

Dường như với tôi rằng họ cũng làm như vậy. Bạn có thể cụ thể hơn không? – Carlo

+0

Trang trí là về việc mở rộng một triển khai khác bằng cách ** gói ** nó trong mã mở rộng. Giải pháp của bạn chỉ gọi các triển khai khác nhau theo trình tự. Đây là [câu trả lời của tôi về trang trí] (http://stackoverflow.com/questions/12379848/decorator-design-pattern-vs-inheritance/12379948#12379948). Cố gắng thực hiện điều đó bằng cách tiếp cận thay đổi mà bạn mô tả và bạn sẽ thấy sự khác biệt –

Trả lời

2

Giải pháp 2 thực sự là sự kết hợp giữa mẫu trang trí và mẫu tổng hợp.

Tôi nghĩ rằng giải pháp 1 tốt hơn giải pháp 2 nếu bạn muốn chỉ thêm hành vi và sử dụng giải pháp 1 + mẫu ghép là tốt hơn nếu bạn cũng cần sử dụng nhiều đối tượng làm một.

Như một câu trả lời tổng quát hơn về việc sử dụng này hai mẫu thấy Difference between the Composite Pattern and Decorator Pattern?

Đây là câu trả lời chính:

Các Composite Pattern cho phép bạn xây dựng một cấu trúc phân cấp (ví dụ như một cái cây của các yếu tố) theo cách cho phép mã bên ngoài của bạn xem toàn bộ cấu trúc dưới dạng một thực thể duy nhất. Vì vậy, giao diện cho một thực thể lá chính xác giống như thực thể cho một thực thể phức hợp. Vì vậy, bản chất là tất cả các yếu tố trong cấu trúc tổng hợp của bạn có cùng một giao diện mặc dù một số là các nút lá và một số khác là toàn bộ cấu trúc. Giao diện người dùng thường sử dụng phương pháp này để cho phép tính tương thích dễ dàng.

http://en.wikipedia.org/wiki/Composite_pattern

Các mô hình trang trí cho phép một thực thể hoàn toàn chứa thực thể khác để sử dụng trang trí trông giống hệt với các thực thể kiềm chế. Điều này cho phép người trang trí sửa đổi hành vi và/hoặc nội dung của bất kỳ hành vi nào được đóng gói mà không thay đổi ngoại hình của thực thể. Ví dụ, bạn có thể sử dụng một trình trang trí để thêm đầu ra ghi nhật ký về việc sử dụng phần tử được chứa mà không thay đổi bất kỳ hành vi nào của phần tử được chứa.

http://en.wikipedia.org/wiki/Decorator_pattern

1

là giải pháp 1 (đúng mẫu Decorator) tốt hơn so với giải pháp 2? Tại sao?

Giải pháp 1 tốt hơn giải pháp 2. Giải pháp 1 tuân theo thiết kế Gang of 4 như cũ.

Giải pháp 1 là

  1. Simple
  2. Ít dễ bị lỗi so với giải pháp 2. Bạn phải cư danh sách & rõ ràng danh sách sau khi sử dụng (mà bạn không được hiện đang làm). Nếu bạn đang sử dụng cùng một trang trí trong nhiều chủ đề, bạn phải bảo vệ mã của bạn để thống nhất bộ nhớ.

dụ Bất động thế giới của VendingMachineDecorator có sẵn tại tài liệu này @

When to Use the Decorator Pattern?

Có thể thêm chức năng để loại bỏ các trường hợp trong dung dịch 1?

Có. Có thể. Bạn thêm chức năng xóa trong trang trí trừu tượng và trang trí cụ thể.

public void removeStuff() 

Bạn có thể có một cái nhìn vào bên dưới câu hỏi SE:

How to remove decorated object from Decorator Pattern in Java

Can you remove a decorator?

+0

Các ví dụ để xóa trang trí thực sự tốt. Ở phía bên kia, "Giải pháp 1 là tốt hơn so với Giải pháp 2. Giải pháp 1 theo thiết kế của Gang 4 như nó được." không phải là câu trả lời. Tôi biết giải pháp 1 là tốt hơn, tôi hỏi tại sao nó tốt hơn. Bạn có thể cung cấp câu trả lời cho câu hỏi 1 không? – Carlo

+0

Đã cập nhật câu trả lời. –

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