2011-10-21 188 views
0

所以我在写一个简单的通用矩阵类,跑进了,我不喜欢我的解决方案,所以我想我会请求帮助有更好的一个问题。扩展方法,返回接口类型

考虑此处所描述的接口:

public interface IMatrix<T> 
{ 
    void DeleteColumn(int position); 
    void DeleteRow(int position); 
    // Returns a NEW IMatrix<T> 
    IMatrix<T> FromRows(IList<IList<T>> rows);  // would like to remove 
    // Returns a NEW IMatrix<T> 
    IMatrix<T> FromColumns(IList<IList<T>> columns);// would like to remove 
    IList<IList<T>> GetColumns(); 
    IList<IList<T>> GetRows(); 
    void InsertColumn(int position); 
    void InsertRow(int position); 
    void SetValueAt(int row, int column, T value); 
} 

与扩展

public static class MatrixExtensions 
{ 
    /// <summary> 
    /// Performs a standard matrix addition 
    /// </summary> 
    public static IMatrix<T> Add<T>(this IMatrix<T> matrix, IMatrix<T> other, IScalarOperators<T> operators) 
    { 
     JoinCells<T> joiner = new JoinCells<T>(); 
     return joiner.Join(matrix, other, null, operators.OperatorAdd); 
    } 

    /// <summary> 
    /// Adds a row to the end of the matrix 
    /// </summary> 
    public static void AddRow<T>(this IMatrix<T> matrix); 

    /// <summary> 
    /// Adds a number of rows to the end of the matrix 
    /// </summary> 
    public static void AddRows<T>(this IMatrix<T> matrix, int rows); 

    /// <summary> 
    /// Adds a column to the end of the matrix 
    /// </summary> 
    public static void AddColumn<T>(this IMatrix<T> matrix); 

    /// <summary> 
    /// Adds a number of columns to the end of the matrix 
    /// </summary> 
    public static void AddColumns<T>(this IMatrix<T> matrix, int columns); 

    /// <summary> 
    /// Gets the column at the specified position 
    /// </summary> 
    public static IList<T> ColumnAt<T>(this IMatrix<T> matrix, int position); 

    /// <summary> 
    /// Gets the number of columns in the matrix 
    /// </summary> 
    public static int ColumnCount<T>(this IMatrix<T> matrix); 

    /// <summary> 
    /// Sets the number of columns in the matrix 
    /// </summary> 
    public static void ColumnCount<T>(this IMatrix<T> matrix, int columns); 

    /// <summary> 
    /// Deletes the last column from the matrix 
    /// </summary> 
    public static void DeleteLastColumn<T>(this IMatrix<T> matrix); 

    /// <summary> 
    /// Deletes the last row from the matrix 
    /// </summary> 
    public static void DeleteLastRow<T>(this IMatrix<T> matrix); 

    /// <summary> 
    /// Gets the value at the specified position in the matrix 
    /// </summary> 
    public static T GetValueAt<T>(this IMatrix<T> matrix, int row, int column); 

    /// <summary> 
    /// Multiplies this matrix with the other matrix and returns the result 
    /// </summary> 
    public static IMatrix<T> Multiply<T>(this IMatrix<T> matrix, IMatrix<T> other, IVectorOperators<T> vectorOperators, IScalarOperators<T> scalarOperators) 
    { 
     JoinRowColumn<T> joiner = new JoinRowColumn<T>(); 
     return joiner.Join(matrix, other, vectorOperators.OperatorAdd, scalarOperators.OperatorMultiply); 
    } 

    /// <summary> 
    /// Gets the row at the specified position 
    /// </summary> 
    public static IList<T> RowAt<T>(this IMatrix<T> matrix, int position); 

    /// <summary> 
    /// Gets the number of rows in the matrix 
    /// </summary> 
    public static int RowCount<T>(this IMatrix<T> matrix); 

    /// <summary> 
    /// Sets the number of rows in the matrix 
    /// </summary> 
    public static void RowCount<T>(this IMatrix<T> matrix, int rows); 
} 

考虑乘方法。乘以IMatrix物体的结果是众所周知的。为了简单起见,只考虑矩阵的整数实现。为了计算结果,除了Multiply(int,int)和Add(int,int)如何工作外,我们不需要知道矩阵的任何内容。既然它们都是已知的,那么我不需要其他任何东西来返回一个具有该结果的新矩阵。但是,我不确定这样做的最佳方式。

我的方法是在两种方法FromRows和FromColumns接口加入。这似乎是错误的,因为我不应该以这种特定的方式强制构建矩阵(或者我感觉)。但是,这是唯一可以找出如何返回此接口实例的方法。我将使用IList在joiner类中构建矩阵,并确保该集合是行或列定义,然后使用FromRows方法。这也许会更有意义有一个例子:

/// <summary> 
/// Class used for joining by combining rows and columns 
/// </summary> 
/// <typeparam name="T"> 
/// Type of the values contained in the matrix 
/// </typeparam> 
class JoinRowColumn<T> : IJoinMatrix<T> 
{ 
    public IMatrix<T> Join(IMatrix<T> a, IMatrix<T> b, IOperateVector<T> vectorOperation, IOperateScalar<T> cellOperation) 
    { 
     // ensure that the matricies can be joined 
     if (a.ColumnCount() != b.RowCount()) 
     { 
      throw new ArgumentException("Cannot join matricies. Invalid dimensions"); 
     } 

     IList<IList<T>> rowDefinition = IMatrixHelpers.GetRowDefinition<T>(a.RowCount(), b.ColumnCount()); 
     for (int row = 0; row < a.RowCount(); row++) 
     { 
      IList<T> aRow = a.RowAt(row); 
      for (int col = 0; col < b.ColumnCount(); col++) 
      { 
       IList<T> bCol = b.ColumnAt(col); 
       rowDefinition[row][col] = vectorOperation.Operate(aRow, bCol, cellOperation); 
      } 
     } 
     // I do not like this because it is unclear that the 
     // method is returning a NEW instance of IMatrix<T> 
     // based on the row definition. It does not update 
     // a to contain the matrix defined by rowDefinition 
     return a.FromRows(rowDefinition); // UGLY! 
    } 
} 

所以在方法结束时,我用给我的矩阵的一个产卵(可能)相同类型的新矩阵(虽然有对矩阵返回的具体实现没有限制)。有一部分问题; FromRows返回一个NEW实例。然而,这并不明显,有人可能会认为它正在更新该方法被调用的矩阵。

有没有更好的模式来遵循构建的具体实现的接口的方式加入?或者这种方法看起来好吗?

我刚开始熟悉仿制药所以请容忍我,如果我没有看到什么明显的。

回答

1
  • 包括一个在界面上命名为Construct(int xDimension, int yDimension)方法,返回它
  • 设计一个新的实例,你在这种情况下使用默认的实现。当你对接口进行编码时,没有人应该假定具体的实现。

就个人而言,我会去的第二个选项。无论如何,你正在对接口进行编码,实现并不重要。您可以轻松地返回默认的矩阵实现,并且调用者可以使用它。从理论上讲,你应该考虑为其他方法采用这种方法 - 而不是操纵传入的矩阵,创建一个新的方法并对其进行处理。

这将类似于LINQ的工作方式,并可以防止虫子偷偷在途中。如果你想操纵当前对象,你不需要扩展方法。

+0

我想回到一个默认的实现,然后我想,“如果我选择的默认是次优的...”我认为这是不成熟的,有点尴尬:( – MPavlak

+0

不,我不是。无法再计算手上的次优解决方案的数量,如果您意识到这些解决方案并改进,次优解决方案并不是问题。我们都在学习,而我们正在编码,这就是我们专业的工作方式。 – Femaref