2011-12-21 102 views
1

有問題和答案層次:良好的面向對象設計

所有的
class Answer 
{ 
    int doubtLevel; 
} 
class YesNoAnswer extends Answer 
{ 
    boolean isYes; 
} 
class ColorAnswer extends Answer 
{ 
    int red; 
    int green; 
    int blue; 
} 

class Question 
{ 
    Context ctx; 
    abstract List<? extends Answer> answers; 
} 
class DoesItWorkQuestion extends Question 
{ 
    Thing it; 
    List<YesNoAnswer> answers; 
} 
class IsItTastyQuestion extends Question 
{ 
    Dish dish; 
    List<YesNoAnswer> answers; 
} 
class FavoriteColorQuestion extends Question 
{ 
    List<ColorAnswer> answers; 
} 

首先,我不喜歡包括每個具體類的答案列表只是爲了解決一個答案的類型。有沒有辦法定義一個結構來保持問題以外的答案列表?但答案的類型必須解決一個問題。

然後,我需要創建一個結構,它會爲每個問題的答案保存一個值,例如,假設我想有它計算概率每個答案計算器:

class AnswerProbability<Q extends Question> 
{ 
    Q question; 
//?? 
    double getProbability(???Answer answer){...} 
} 
class ProbabilityCalculator 
{ 
    // different params may produce different answer lists 
    //(e.g. if probability of an answer is less than 1%, don't include 
    //the answer in the list). 
    AnswerProbability<IsItTastyQuestion> tastyQuestionProbability(String param1, String param2); 
    AnswerProbability<FavoriteColorQuestion> favoriteColorQuestion(String param); 
... 
} 
... 

以及它如何被使用:

AnswerProbability<IsItTastyQuestion> prob = calculator.tastyQuestionProbability(...); 
// I want the "get" method take only YesNoAnswer type. 
println(prob.get(new YesNoAnswer(true, 10) + prob.get(new YesNoAnswer(false, 5)); 
// or: 
for(YesNoAnswer ans : prob.question.answers) 
{ 
    if(ans.isYes) 
    println(prob.get(ans)); 
} 
// Also I need work with superclasses 
List<AnswerProbability> aps; 
aps.add(calculator.calculateTastyQuestionProbability("soup", "mushroom")); 
aps.add(calculator.calculateFavoriteColorQuestion("socks")); 
.. 
// use `doubtLevel` from the `Answer` superclass. 
for(AnswerProbability ap : aps) 
{ 
    for(Answer a : ap.question.answers) 
    { 
    if(a.doubtLevel < 5) 
     println(ap.get(a)); 
    } 
} 

所以,我要避免進行類型強制轉換和運行時檢查。

回答

1

你不能有一個抽象的領域。你可以在這裏使用泛型

class Question<A extends Answers> { 
    Context ctx; 
    final List<A> answers = new ArrayList<A>(); 
} 

class DoesItWorkQuestion extends Question<YesNoAnswer> { 
    Thing it; 
} 

class FavoriteColorQuestion extends Question<ColorAnswer> { 
} 

但是我懷疑什麼會更有用的是記錄每個答案的計數。

class Question<A extends Answers> { 
    Context ctx; 
    final Map<A, Integer> answerCounts = new HashMap<>(); 
} 

class DoesItWorkQuestion extends Question<YesNoAnswer> { 
    Thing it; 
} 

class FavoriteColorQuestion extends Question<ColorAnswer> { 
} 

// later 
for(Entry<YesNoAnswer, Integer> ansCount : prob.question.answers.entrySet()) { 
    switch(ansCount.getKey()) { 
     case YES: 
      int count = ansCount.getValue(); 
      // something 
      break; 
    } 
} 

由於大小與可能答案的數量成正比,而不是答案的數量和計算概率非常容易,所以這樣更有效。

+0

如果我使用類型參數'A',那麼'AnswerProbability'(和其他我沒有在這裏提到過的類)也應該被這個參數放大(見http://stackoverflow.com/questions/8416664/eliminate型參數-的-java的泛型)。我不能使用'Map '因爲我需要不同的結構,例如而不是'Integer'我可以有'enum Popularity'或'Double probability'等。我試着將這個類型作爲另一個參數,但是發現'DoesItWorkQuestion '和'DoesItWorkQuestion '具有不兼容的類型。 – kan 2011-12-21 20:00:11