2016-07-28 84 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); 
相关问题