2016-07-28 7 views
0

Ich habe die Hierarchie der Matrix-Klassen. Ich möchte did't meine Klassen ändern, also entschied ich mich Besuchermuster zu verwenden, wie Matrix-Operationen umfassen wie Addition, Multiplikation usw. Meine Hierarchie wie das aussieht:Wie kann das Besuchermuster in einer Hierarchie generischer Klassen am besten verwendet werden?

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> {} 

Alle diese Klassen implementieren Methode Accept:

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

Aber ich wurde durch Zugabe von zwei Elementen stucked die Art T. habe ich nicht weiß, T haben Betreiber geben wird ‚+‘ überlastet. Ich habe mich dafür entschieden, Delegat Func wie Parameter des konkreten Besuchers zu verwenden. Und jetzt sieht meine konkrete Besucher Klasse wie folgt:

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]); 
     } 
} 

ich mich wirklich hassen, denn wenn ich hinzufügen mag oder multiplizieren quadratische Matrix und Diagonalmatrix Ich habe eine Instanz Besucher zu schaffen und definieren wieder Betrieb. Gibt es einen eleganteren Weg? Vielen Dank.

Antwort

0

Normalerweise wird die Ausführung der Operation vom Typ des Besuchers bestimmt, und die Unterscheidung der Operationen nach dem Operandentyp wird durch die überladenen Besuchermethoden definiert. Dies nennt man doppelten Versand. In Ihrem Fall ein Besucher würde einig generische binäre Matrix-Operation muss so aussehen Umsetzung:

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 
} 

einen Besucher Mit einer binären Operation zu implementieren ist recht ungewöhnlich, wie Sie überladene Methoden für alle Kombinationen von Operanden implementieren müssen Arten.

Aber in Ihrem speziellen Fall, wenn Sie nur auf Additionen und Multiplikationen beschränkt sind, müssen Sie das nicht tun. Diese Operationen hängen nicht von den Beschränkungen ab, die geerbte Klassen der Basis-Matrix-Klasse hinzufügen: Solange zwei Matrizen kompatible Elementtypen und übereinstimmende Dimensionen haben, ist es egal, ob sie diagonal oder was nicht sind. So können Sie einen allgemeinen Summe Besucher für alle Arten von Matrizen realisieren mit nur einem Verfahren:

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. 
    } 
} 

Aber wenn dies der Fall ist, brauchen Sie nicht einen Besucher überhaupt, wie Sie jetzt einen Einzelversand durchführen - nur nach dem Typ des Besuchers. In diesem Fall können Sie die Akzeptieren Methode vollständig ablegen - es würde nichts nützliches neben dem Weiterleiten des Anrufs tun. Stattdessen tun Sie dies:

Matrix<int> a, b; 
// ... 
MatrixBinaryOp op = new MatrixSum(...); 
var sum = op.Operation(a, b); 
Verwandte Themen