2016-07-28 57 views
0

我有矩陣類的層次結構。餘did't想改變我的課,所以我決定用訪問者模式包括這樣的矩陣運算像加法,乘法,等我的層次看起來像這樣:在泛型類層次結構中使用訪問者模式的最佳方式是什麼?

public abstract class Matrix<T> { 
    public abstract T GetValue(int i, int j); 
    public abstract void SetValue(int i, int j, T value); 
    public abstract Matrix<T> Accept(MatrixVisitor<T> visitor, Matrix<T> matrix); 
} 

public class SquareMatrix<T> : Matrix<T> {} 
public class DiagonalMatrix<T> : Matrix<T> {} 
public class SymmetricMatrix<T> : Matrix<T> {} 

所有這些類的實現Accept方法:

public override Matrix<T> Accept(MatrixVisitor<T> visitor, Matrix<T> matrix) 
     { 
      return visitor.Operation(this, matrix); 
     } 

但是我與另外具有類型T.我不知道將類型T的兩個元素的stucked重載運算符「+」。我決定使用具體訪客的參數等委託Func。現在我的具體訪問類看起來是這樣的:

public class SumOfSquareMatricesVisitor<T> : MatrixVisitor<T> 
    { 
     public SumOfSquareMatricesVisitor(Func<T, T, T> sumOfTwoTypesOperation) 
     { 
      this.sumOfTwoTypesOperation = sumOfTwoTypesOperation; 
     } 

     public override Matrix<T> Operation(Matrix<T> A, Matrix<T> B) 
     { 
      // example 
      // into a loop 
      // result = sumOfTwoTypesOperation(A[i,j], B[i,j]); 
     } 
} 

我真的很討厭我的方式,因爲如果我要相加或相乘方陣和對角矩陣我要創建訪問者的實例,並重新定義操作。有沒有更優雅的方式?謝謝。

回答

0

通常,正在執行的操作由訪問者的類型決定,操作數類型的操作區分由重載的訪問者方法定義。這叫做雙派遣。在你的情況訪問者實施一些通用二進制矩陣運算必須是這樣的:

public class SomeOperationVisitor<T> : BinaryOperationMatrixVisitor<T> 
{ 
    public SomeOperationVisitor(Func<T, T, T> someItemOp) 
    { 
    this.someItemOp = someItemOp; 
    } 

    public override Matrix<T> Operation(SquareMatrix<T> a, SquareMatrix<T> b) 
    { ... } 

    public override Matrix<T> Operation(SquareMatrix<T> a, DiagonalMatrix<T> b) 
    { ... } 

    // other methods for all combination of element types 
} 

使用訪問者實現二進制操作是相當不尋常,因爲你必須實現的操作數的所有組合重載方法類型。

但在你的特殊情況下,如果你僅限於增加和乘法,你不必這樣做。這些操作不依賴於繼承的類添加到基本Matrix類的約束:只要兩個矩陣具有兼容的元素類型和匹配的維度,則不必關心它們是對角還是其他。所以,你可以實現對所有類型的矩陣的通用和遊客,只有一個方法:

public class MatrixSumVisitor<T> : BinaryOperationMatrixVisitor<T> 
{ 
    public MatrixSumVisitor(Func<T, T, T> addOp) 
    { 
    this.addOp = addOp; 
    } 

    public override Matrix<T> Operation(Matrix<T> a, Matrix<T> b) 
    { 
    // 1. Check that dimensions of a and b match. 
    // 2. Add a and b. 
    } 
} 

但是,如果是這樣的話,你並不需要一個訪問者都因爲你現在執行單牒 - 僅限訪問者類型。在這種情況下,您可以完全拋棄接受方法 - 除了簡單轉發呼叫之外,它不會執行任何有用的操作。而是這樣做:

Matrix<int> a, b; 
// ... 
MatrixBinaryOp op = new MatrixSum(...); 
var sum = op.Operation(a, b); 
相關問題