責任鏈模式探討

tbase發表於2004-03-03
責任鏈模式定義:
閻宏的定義:"發出這個請求的客戶端並不知道鏈上的那一個物件最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織鏈和分配責任."

閻宏的定義很精煉,但是太精煉的以至於很多人很難理解。
定義分解如下:
1 服務端有一組策略(也可以稱之為方法,演算法等等)按順序處理請求。這組策略的組織順序與客戶端無關。
2 當這組策略中的某一個策略滿足結束條件時,整個責任鏈結束。

解釋:責任鏈模式可以被認為是“策略物件順序執行”。在一個順序策略連結串列中的策略按順序被呼叫。當某種策略滿足要求,就返回成功標誌或者責任鏈結束。


注意的是Gof的例子沒有使用連結串列。



這個例子非常好的揭示了責任鏈模式的奧秘:

//: chainofresponsibility:FindMinima.javaimport junit.framework.*;class Arrays2 {
  public static String toString(double[] a) {    
    StringBuffer result = new StringBuffer("[");    
    for(int i = 0; i < a.length; i++) {      
       result.append(a[i]);      
       if(i < a.length - 1)
         result.append(", ");    
    }    
    result.append("]");    
    return result.toString();  
   }
}

// Carries the result data and 
// whether the strategy was successful:
class LineData {
  public double[] data;
  public LineData(double[] data) { this.data = data; }
  private boolean succeeded;
  public boolean isSuccessful() { return succeeded; }
  public void setSuccessful(boolean b) { succeeded = b; }
}

interface Strategy {
  LineData strategy(LineData m);
}

class LeastSquares implements Strategy {
  public LineData strategy(LineData m) {
    System.out.println("Trying LeastSquares algorithm");
    LineData ld = (LineData)m;
    // [ Actual test/calculation here ]
    LineData r = new LineData(
      new double[] { 1.1, 2.2 }); // Dummy data
    r.setSuccessful(false);
    return r;
  }
}

class NewtonsMethod implements Strategy {
  public LineData strategy(LineData m) {
    System.out.println("Trying NewtonsMethod algorithm");
    LineData ld = (LineData)m;
    // [ Actual test/calculation here ]
    LineData r = new LineData(
      new double[] { 3.3, 4.4 }); // Dummy data
    r.setSuccessful(false);
    return r;
  }
}

class Bisection implements Strategy {
  public LineData strategy(LineData m) {
    System.out.println("Trying Bisection algorithm");
    LineData ld = (LineData)m;
    // [ Actual test/calculation here ]
    LineData r = new LineData(
      new double[] { 5.5, 6.6 }); // Dummy data
    r.setSuccessful(true);
    return r;
  }
}

class ConjugateGradient implements Strategy {
  public LineData strategy(LineData m) {
    System.out.println(
      "Trying ConjugateGradient algorithm");
    LineData ld = (LineData)m;
    // [ Actual test/calculation here ]
    LineData r = new LineData(
      new double[] { 5.5, 6.6 }); // Dummy data
    r.setSuccessful(true);
    return r;
  }
}

class MinimaFinder {
  private static Strategy[] solutions = {
    new LeastSquares(),
    new NewtonsMethod(),
    new Bisection(),
    new ConjugateGradient(),
  };
  public static LineData solve(LineData line) {
    LineData r = line;
    for(int i = 0; i < solutions.length; i++) {
      r = solutions[i].strategy(r);
      if(r.isSuccessful())
        return r;
    }
    throw new RuntimeException("unsolved: " + line);
  }
}
  
public class FindMinima extends TestCase  {
  LineData line = new LineData(new double[]{ 
    1.0, 2.0, 1.0, 2.0, -1.0, 3.0, 4.0, 5.0, 4.0
  });
  public void test() {
    System.out.println(Arrays2.toString(
      ((LineData)MinimaFinder.solve(line)).data));
  }
  public static void main(String args[]) {
    junit.textui.TestRunner.run(FindMinima.class);
  }
} ///:~
<p class="indent">

相關文章