2012-02-15 26 views
6

Xét đoạn mã sau:cư Danh sách cha mẹ yếu tố dựa trên con đánh giá cao

CLASS AuditProgressReport:

public class AuditProgressReport 
{ 
    private List<AuditProgressReport> audit_progress_reports = null; 

    private String name = null; 
    private String description = null; 

    private int compliant; 
    private int non_compliant; 
    private int not_completed ; 

    /** 
    * 
    */ 
    public AuditProgressReport() 
    { 
     super(); 
    } 

    public AuditProgressReport(
     String name_param, 
     int compliant_param, 
     int non_compliant_param, 
     int not_completed_param) 
    { 
     super(); 

     this.name = name_param; 
     this.compliant = compliant_param; 
     this.non_compliant = non_compliant_param; 
     this.not_completed = not_completed_param; 
    } 

    public void addToCompliant(int compl_to_add_param) 
    { 
     this.compliant += compl_to_add_param; 
    } 

    public void addToNonCompliant(int non_compl_to_add_param) 
    { 
     this.non_compliant += non_compl_to_add_param; 
    } 

    public void addToNotCompleted(int not_compl_param) 
    { 
     this.not_completed += not_compl_param; 
    } 

    public void setAuditProgressReports(List<AuditProgressReport> report_category_nodes_param) 
    { 
     this.audit_progress_reports = report_category_nodes_param; 
    } 

    public List<AuditProgressReport> getAuditProgressReports() 
    { 
     return this.audit_progress_reports; 
    } 

    public void setCompliant(int compliantParam) 
    { 
     this.compliant = compliantParam; 
    } 

    public int getCompliant() 
    { 
     return this.compliant; 
    } 

    public void setNonCompliant(int nonCompliantParam) 
    { 
     this.non_compliant = nonCompliantParam; 
    } 

    public int getNonCompliant() 
    { 
     return this.non_compliant; 
    } 

    public void setNotCompleted(int notCompletedParam) 
    { 
     this.not_completed = notCompletedParam; 
    } 

    public int getNotCompleted() 
    { 
     return this.not_completed; 
    } 

    public void setName(String name_param) 
    { 
     this.name = name_param; 
    } 

    public String getName() 
    { 
     return this.name; 
    } 

    public void setDescription(String description_param) 
    { 
     this.description = description_param; 
    } 

    public String getDescription() 
    { 
     return this.description; 
    } 

    @Override 
    public String toString() 
    { 
     return ("Compliant["+this.compliant+ 
      "] Non-Compliant["+this.non_compliant+ 
      "] Not-Completed["+this.not_completed+"]"); 
    } 
} 

Và CLASS Tester:

public class Tester 
{ 
    public static void main(String[] args) 
    { 

     List<AuditProgressReport> main_level = new ArrayList<AuditProgressReport>(); 

     AuditProgressReport ar_1_1 = new AuditProgressReport("ar_1_1",0,0,0); 
     AuditProgressReport ar_1_2 = new AuditProgressReport("ar_1_2",0,0,0); 

     AuditProgressReport ar_1_1_1 = new AuditProgressReport("ar_1_1_1",0,0,0); 
     AuditProgressReport ar_1_1_2 = new AuditProgressReport("ar_1_1_2",15,65,20); 
     AuditProgressReport ar_1_1_3 = new AuditProgressReport("ar_1_1_3",20,30,50); 

     AuditProgressReport ar_1_1_1_1 = new AuditProgressReport("ar_1_1_1_1",5,5,90); 
     AuditProgressReport ar_1_1_1_2 = new AuditProgressReport("ar_1_1_1_2",55,5,40); 
     AuditProgressReport ar_1_1_1_3 = new AuditProgressReport("ar_1_1_1_3",35,35,30); 

     List<AuditProgressReport> arl_1_1_1 = new ArrayList<AuditProgressReport>(); 
     arl_1_1_1.add(ar_1_1_1_1); 
     arl_1_1_1.add(ar_1_1_1_2); 
     arl_1_1_1.add(ar_1_1_1_3); 

     ar_1_1_1.setAuditProgressReports(arl_1_1_1); 

     List<AuditProgressReport> arl_1_1 = new ArrayList<AuditProgressReport>(); 
     arl_1_1.add(ar_1_1_1); 
     arl_1_1.add(ar_1_1_2); 
     arl_1_1.add(ar_1_1_3); 

     AuditProgressReport ar_1_2_1 = new AuditProgressReport("ar_1_2_1",10,30,60); 
     AuditProgressReport ar_1_2_2 = new AuditProgressReport("ar_1_2_2",20,20,60); 



     List<AuditProgressReport> arl_1_2 = new ArrayList<AuditProgressReport>(); 
     arl_1_2.add(ar_1_2_1); 
     arl_1_2.add(ar_1_2_2); 

     ar_1_1.setAuditProgressReports(arl_1_1); 

     ar_1_2.setAuditProgressReports(arl_1_2); 

     main_level.add(ar_1_1); 
     main_level.add(ar_1_2); 


     Tester tester = new Tester(); 

     for(AuditProgressReport prog_rep : main_level) 
     { 
      tester.populateParents(prog_rep, null); 
     } 

     //TODO Now check the values... 
    } 

    private void populateParents(
     AuditProgressReport audit_progress_param, 
     AuditProgressReport parent_param) 
    { 
     List<AuditProgressReport> audit_progress = 
      audit_progress_param.getAuditProgressReports(); 

     System.out.println("name["+audit_progress_param.getName()+"]"); 

     if(parent_param != null) 
     { 
      int compl = audit_progress_param.getCompliant(); 
      int nonCompl = audit_progress_param.getNonCompliant(); 
      int notCompleted = audit_progress_param.getNotCompleted(); 

      parent_param.addToCompliant(compl); 
      parent_param.addToNonCompliant(nonCompl); 
      parent_param.addToNotCompleted(notCompleted); 
     } 

     if(audit_progress != null && ! audit_progress.isEmpty()) 
     { 
      for(AuditProgressReport prog_rep : audit_progress) 
      { 
       this.populateParents(prog_rep,audit_progress_param); 
      } 
     } 
    } 
} 

Khi bạn chạy này, bạn sẽ lưu ý rằng các giá trị của các phần tử cha trong danh sách được cập nhật với tổng của các giá trị trong danh sách con.

Sự cố tôi đang gặp phải là tôi muốn cập nhật tất cả thông qua cây thay vì chỉ cha mẹ trực tiếp.

Có mẫu nào giúp tôi đạt được điều này không?

Xem hình minh họa bên dưới:

enter image description here

+2

Đối với mỗi nút, hãy đặt giá trị của nó thành tổng các giá trị của trẻ em. Mùi giống như đệ quy;) –

+0

Bạn không thể làm cho mỗi người nghe cha mẹ của nó là trẻ em? Cũng sẽ giúp bạn tiết kiệm một số rắc rối cập nhật thủ công. – bdecaf

Trả lời

4

Giống như những người khác đề nghị tôi sẽ sử dụng mẫu Observer. Mỗi nút cha lắng nghe những thay đổi trên childrens.

Nhưng giải pháp của tôi khác với @zmf vì nếu bạn có một cây lớn có nhiều nút con và mỗi lần cập nhật bạn phải tính tổng giá trị, bạn sẽ tốn nhiều thời gian xử lý.

Nếu bạn chỉ gửi sự khác biệt giữa giá trị cũ và giá trị mới mỗi khi bạn cập nhật nút con. Hãy làm một ví dụ. Bạn bắt đầu với cây này:

[12]--+--[10]-----[10] 
     | 
     +--[ 2]--+--[ ] 
       | 
       +--[ 2] 

và bạn cập nhật dành cho trẻ em như thế này

[12]--+--[10]-----[10] 
     | 
     +--[ 2]--+--[ 3] 
       | 
       +--[ 2] 

nút đó được cập nhật với các giá trị "3" gửi thay đổi của mình cho phụ huynh với phụ huynh gọi phương thức. updateNode (3). Cha mẹ chỉ có tổng giá trị hiện tại của nó (trong ví dụ này "2") với giá trị nó nhận được từ nút con. Vì vậy, nó sẽ cập nhật với giá trị "5"

[12]--+--[10]-----[10] 
     | 
     +--[ 5]--+--[ 3] 
       | 
       +--[ 2] 

nút với giá trị mới "5" sẽ gọi parent.updateNode (3) và giải pháp cuối cùng sẽ

[15]--+--[10]-----[10] 
     | 
     +--[ 5]--+--[ 3] 
       | 
       +--[ 2] 

IMHO giải pháp này là tốt hơn bởi vì mỗi phương thức updateNode() chỉ có tổng giá trị hiện tại của riêng nó với thay đổi nhận được từ nút con của nó và gọi cha mẹ của nó với cùng một giá trị nhận được. Bạn không cần phải lấy giá trị từ mỗi con của bạn và tổng hợp tất cả các giá trị. Điều này sẽ giúp bạn tiết kiệm rất nhiều thời gian nếu bạn có một cây lớn. Vì vậy, trong ví dụ này khi bạn thay đổi giá trị từ 0 đến 3. Bạn sẽ nhận được 2 cuộc gọi đến parent.updateNode (3) và mỗi phụ huynh sẽ được cập nhật.

2
public void updateNode(int value) { 

    if (value != this.value) { 
     this.value = value; 

     if (getParent() != null) { 
      int sum = 0; 
      for (Node n : getParent().getChildren()) { 
       sum += n.getValue(); 
      } 
      getParent.updateNode(sum); 
     } 
    } 
} 
1

Áp phích khác đề xuất sử dụng số Observer pattern. Mẫu Observer là một tập con của Pub/Sub pattern. Tôi khuyên bạn nên sử dụng mẫu này trên mẫu Observer.

Sự khác biệt chính giữa mẫu Observer và mẫu Pub/Sub là trong mẫu Observer, Observer vừa là nhà xuất bản ChangeEvents vừa là người điều phối tin nhắn. Nó chủ yếu làm cho mọi Observable trở thành EventDispatcher. Trong mẫu Pub/Sub truyền thống, Observables chỉ là các ChangeEvents của nhà xuất bản. ChangeEvents được xuất bản cho một EventDispatchingService riêng biệt, xử lý những gì mà các thuê bao các sự kiện cần được gửi đến.

Cố gắng theo dõi các thay đổi toàn cục bằng mẫu Observer rất khó thực hiện. Ví dụ: nếu bạn muốn đếm số lần thời gian phương thức addToCompliant() được gọi, bạn sẽ phải thêm Trình quan sát trên mọi phiên bản của Observable. Với Event Pub/Sub, lớp người quan sát của bạn chỉ có thể đăng ký nghe trên loại ChangeEvent và nó sẽ nhận tất cả chúng. Thư viện Pub/Sub Event (IMHO) tốt nhất mà tôi đã sử dụng là Google Guava's Event Bus. Trong trường hợp cụ thể của bạn, tôi sẽ làm một cái gì đó như sau.

public class EventBusSingleton { 
    public static final EventBus INSTANCE = new EventBus("My Event Bus"); 
} 

public class ComplianceChange { 
    private AuditProgressReport changedReport; 
    private int delta; 

    public ComplianceChange(AuditProgressReport changedReport, int delta) { 
     this.changedReport = changedReport; 
     this.delta = delta; 
    } 

    ... 
} 

public class AuditProgressReport { 

    ... 
    private AuditProgressReport parent; 

    public AuditProgressReport getParent() { 
     return parent; 
    } 

    public void addToCompliant(int delta) { 
     this.compliant += delta; 
     ComplianceChange change = new ComplianceChange(this, delta); 
     EventBusSingleton.INSTANCE.post(change); 
    } 
    ... 
} 

public class ComplianceChangeHandler { 

    @Subscribe 
    public void notifyParent(ComplianceChange event) { 
     AuditProgressReport parent = event.getChangedReport().getParent(); 
     int delta = event.getDelta(); 
     parent.addToCompliant(delta); 
    } 

    @Subscribe 
    public void somethingElse(ComplianceChange event) { 
     // Do Something Else 
    } 
} 

// Somewhere during initialization 
EventBusSingleton.INSTANCE.register(new ComplianceChangeHandler()); 
+0

Tôi nghĩ mẫu Pub/Sub không phải là lựa chọn tốt nhất cho vấn đề này bởi vì vấn đề quá đơn giản để sử dụng mẫu đó. Trong vấn đề này chỉ có nút cha trực tiếp muốn biết những thay đổi trong các giá trị của các con của nó. Tôi sẽ sử dụng mẫu Pub/Sub cho các vấn đề phức tạp hơn, đó là cho giao tiếp không đồng bộ giữa hai lớp không tương quan trên hai gói khác nhau. Infact với gói này hai phần của giao tiếp không thể biết nhau tại compiletime hoặc thời gian chạy. – PinoSan

0

Dựa trên tên lớp học của bạn, tôi đoán bạn muốn xem tiến trình kiểm tra của mình hoạt động khi chạy. Vì vậy, giả thuyết của tôi:

  • cơ cấu cây không thay đổi quá nhiều, gần như cố định sau khi tạo
  • giá trị nút thay đổi thường xuyên, quầy bán hàng quốc gia ban đầu là 0

Dưới đây là một thực hiện hiệu quả:

  • mỗi nút duy trì danh sách đầy đủ các nút cha của nó
  • các nút được chèn với giá trị 0
  • khi một giá trị nút được thay đổi hoặc chỉ đơn giản là tăng, giá trị của cha mẹ ra khỏi danh sách của nút được cập nhật bằng cách áp dụng các đồng bằng giữa giá trị nút trước

Kết quả là cấu trúc phải lúc nào cũng up-to-date , nút chèn vẫn có thể và không ảnh hưởng đến các nút hiện có.

Nếu nhiều chủ đề kiểm tra chạy đồng thời và báo cáo giá trị vào cấu trúc, bạn phải cẩn thận với các vấn đề tương tranh và sử dụng AtomicInteger làm chủ sở hữu bộ đếm.

Đây là một thiết kế thực dụng và chân thành tôi không tìm thấy bất kỳ mẫu phù hợp nào. Giống như các thuật toán sắp xếp, cố gắng sử dụng các mẫu trong ngữ cảnh như vậy có thể phản tác dụng.

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