2016-07-25 19 views
0

Ich habe eine Frage in Bezug auf Architektur/Funktionalität:Architektur von Erbschaften mit allen Parameterkombinationen

Lets für ein gegebenes Problem sagen, dass ich einen Algorithmus haben, der das Problem löst. Es kann eine bestimmte Menge an Informationen verwenden, die durch ein Objekt repräsentiert werden, das einige Instanzvariablen generischer Typen enthält. Tatsächlich gibt es n Variablen, die relevant sind, aber der Algorithmus kann das Problem mit einer unbekannten Teilmenge lösen. Um diese Teilmenge zu finden, möchte ich in der Lage sein, jede mögliche Kombination von Variablen an den Algorithmus zu übergeben. Ich möchte also eine Struktur, mit der ich mit möglichst wenig Aufwand zwischen den Informationsarten wechseln kann.

Insbesondere zwei Informationsobjekte sollten gleich sein, wenn nur die aktuell untersuchte Teilmenge von Variablen gleich ist. So scheint es, dass ich gleiches überschreiben muss. Dies würde bedeuten, eine Klasse für jede mögliche Untergruppe zu schreiben, was zu insgesamt 2 Klassen führt.

Gibt es einen eleganteren Weg, dies zu tun? Und wenn es die 2^n Klassen sein müssten, wie würden Sie die Erbschaften entwerfen?


Als Antwort auf Andy Turners und mellowmaroons Kommentar: Ich habe den Solver vorstellen eine Funktion f sein: S -> {0,1}, die mir die richtige Aktion (0 oder 1) für einen bestimmten Status erzählen s . Der Status s ist durch einen Vektor der Länge k gegeben. Um es einfach zu halten, nehme man einfach S = Z^k, z.B. Ganzzahlen. Aber es kann ausreichen, den Statusraum mit einer unbekannten Teilmenge von Variablen aufzubauen, die zu S = Z^l, l < k führt. Um die möglichen Teilmengen zu testen, muss der Algorithmus mit Objekten des entsprechenden Statusraums laufen. Während des Prozesses werden Objekte des Statusraums generiert und an das Solver-Objekt übergeben. Der Löser sollte in der Lage sein, sie zu akzeptieren, und er muss in der Lage sein, einen Status zu erkennen, der bereits existiert. Allgemein gefragt, wie ist das zu strukturieren?


Hier ist ein Beispiel meines aktuellen Ansatzes

//abstract superclass to wrap the information types 

    public abstract class Information { 

    } 

// concrete class that contains 1st and 2nd parameters 

    public class InformationA extends Information{ 

     int size; 
     int weight; 

    // two InformationA objects are equal if only 1st and 2nd parameter are equal 

    public boolean equals(Object o){ 
     if(o instanceof InformationA){ 
      InformationA info = (InformationA) o; 
      return info.size == size && info.weight == weight; 
     } 
     return false 
    } 

// concrete class that contains 2nd and 3rd Parameters 

    public class InformationB extends Information { 

     int weight; 
     int color; 

     //another equals method with the same structure than before 

    } 

import java.util.HashMap; 
import java.util.Random; 

// the solver class contains the solve function 
// It associates an action with every possible status/information 

public class Solver { 

    HashMap<Information, Boolean> solveFunction; 

    // If a status/information has been treated already return the value 
    // else generate a random value 

    public Boolean getAction(Information i){ 
     if(solveFunction.containsKey(i)) return solveFunction.get(i); 
     solveFunction.put(i, new Random().nextInt(2) == 0); 
     return solveFunction.get(i); 
    } 

    public void solve(Problem problem){ 
//  while(!problem.isSolved()){ 
//##  somehow extract only the needed status Parameters 
//   pass them to getAction method and invoke the response on the problem 
//  } 
    } 

} 

public class Problem { 

// public boolean isSolved(){ 
//  return some signal 
// } 

// public void process(Boolean action){ 
//  the process develops according to the action and reaches a new state 
//  } 

//## public getStatus(){ 
//  return the status in a way that the solver can extract the needed subset of information 
// } 

} 

public class Controller { 

// generate the problem and the solver 
//##somehow tell the solver which Information type to use 
// Let the solver solve the problem  

    public static void main(String[] args){ 
     Problem problem = new Problem(); 
     new Solver().solve(problem); 
    } 

} 

Es ist offensichtlich, dass dieser Ansatz für das Problem führt die erforderliche Teilmenge zu erzeugen und es zu Solver übergeben. Dies könnte lösbar sein. Aber es gibt immer noch das Problem, alle Informationsklassen mit den verschiedenen Parameterkombinationen zu schreiben.

+1

Warum denken Sie, dass Vererbung der richtige Weg ist, alle Kombinationen zu modellieren? Wenn Sie einen generischen Solver haben, benötigen Sie einen Typ, der generisch funktioniert. Sie können es nur tun, wenn alle diese "Parametertypen" eine gemeinsame Schnittstelle haben. –

+0

Ich denke, du solltest klarstellen, was genau du fragst. Objektorientierte Konzepte sind nicht nur auf Java beschränkt. Sie sollten Ihre Tags möglicherweise überarbeiten, wenn Ihre Frage OOP als Ganzes betrifft. – mellowmaroon

+0

Haben Sie ein Codebeispiel, das zwei verschiedene Unterklassen mit Ihrer aktuellen Implementierungsidee zeigt? Das Problem ist ein wenig zu allgemein beschrieben und es fehlen reale Details. – plalx

Antwort

0

Nun, diese Frage ist ziemlich alt. Ich denke, dass ich bei der Lösung etwas Fortschritte gemacht habe, also poste ich meinen Ansatz und hoffe auf etwas Feedback oder Verbesserung.

Um zwischen verschiedenen Parameterkombinationen zu wechseln, habe ich versucht, Unterklassen einer Oberklasse "Information" zu verwenden. Stattdessen verwende ich jetzt eine HashMap, um eine Instanz einer Information-Klasse darzustellen, und eine HashMap dieser HashMaps repräsentiert die Funktion f, die jeder Informationsinstanz eine Aktion zuweist.

// the class that represents first parameter 

public class A{ 
    //can be a selfmade class or a String or some generic type 
} 

// same for parameters B,C,D,E... 

import java.util.HashMap; 
import java.util.Random; 

// the solver class fills the solveFunction HashMap 
// It associates an action with every possible status/information 

public class Solver { 

    HashMap<HashMap<String,Object>, Boolean> solveFunction; 

    // If a status/information has been treated already return the value 
    // else generate a random value 

    public Boolean getAction(HashMap<String, Object> info){ 
     if(solveFunction.containsKey(info)) return solveFunction.get(info); 
     solveFunction.put(info, new Random().nextInt(2) == 0); 
     return solveFunction.get(info); 
    } 

    public HashMap<HashMap<String, Object>, Boolean> solve(Problem problem, HashMap<HashMap<String, Object>, Boolean> solveFunction){ 
     this.solveFunction = solveFunction; 
     while(!problem.isSolved()){ 
      problem.process(getAction(problem.getStatus())); 
     } 
    } 

} 

public class Problem { 

String[] usedParameters; 

public Problem(String[] usedParameters){ 
    this.usedParameters = usedParameters; 
} 

    public boolean isSolved(){ 
//  return a signal 
    } 

    public void process(Boolean action){ 
//  the process develops according to the action and reaches a new state 
     } 

public getStatus(){ 
    HashMap<String, Object> status = new HashMap(); 
    for(String s : usedParameters){ 
     switch(s){ 
      case "A": status.add("A", new Object()); 
      case "B": status.add("B", new Object()); 
      case "C": status.add("C", new Object()); 
// and so on 
     } 
    } 
    return status; 
} 
} 

public class Controller { 

// generate the problem and the solver 
// Let the solver solve the problem  

    public static void main(String[] args){ 
     String[] usedParameters = {"A","C"}; 
     HashMap<HashMap<String, Object>, Boolean> solveFunction = new HashMap(); 
     Problem problem = new Problem(usedParameters); 
     new Solver().solve(problem, solveFunction); 
    } 

} 

Der obige Code funktioniert natürlich nicht, sollte aber nur die Idee geben. Der Fall, dass die zufällig generierte Solve-Funktion fehlschlägt, muss abgefangen werden. Ich denke, dass der Rest des Codes nicht abgeschlossen werden kann, ohne die Allgemeinheit zu verlieren.