How to add the value of all the objects?

2019-09-29 04:42发布

问题:

Let's say we have a class SCORE. It has three objects s1,s2 and s3. SCORE has an attribute RUNS. How to add the runs of all the objects ? SCORE has an internal method int TOTALSCORE(). so when that method is called, it should return the total score .

How should i call that method ? Like s1.TOTALSCORE() ? Or any other way?

回答1:

In rare cases the thing that you want could be reasonably, but normally the class is not aware of all it's elements. A total Score is for a Collection of Score elements, maybe a List or a Set.

So you would do:

class Score {
  int value;
  // ...
  public static int totalScore(Collection<Score> scores){ 
    int sum = 0;
    for (Score s: scores){
      sum += s.value;
    }
    return sum;
  }
}

And outside you would have

List<Score> myBagForScores = new ArrayList<>();
Score e1 = new Score...
myBagForScores.add(e1);
// e2, e3 and so on
int sum = Score.totalScore(myBagForScores);

Hope that helps!



回答2:

Here is a small Proof-Of-Concept:

public class Score {

private static ReferenceQueue<Score> scoreRefQueue = new ReferenceQueue<Score>();

private static List<WeakReference<Score>> runs = new ArrayList<WeakReference<Score>>();

static { // remove references to instances that are Garbage Collected
    new Thread(new Runnable() {
        @Override
        public void run() {
            while(true) try {
                Object scoreRef = scoreRefQueue.remove(); // blocks until next reference is available
                synchronized(runs) {                      // synch access with summing iterator
                    runs.remove(scoreRef);
                }
            } catch(Throwable t) {
                // ignore
            }
        }
    }).start();
}

/**
 * The factory method
 */
public static Score getInstance() {
    final Score score = new Score();
    final WeakReference<Score> scoreRef = new WeakReference<Score>(score, scoreRefQueue);
    synchronized(runs) {
        runs.add(scoreRef);
    }
    return score;
}

private int total;

private Score() {
    // prevent creating instances outside this class
}

/**
 * The service method
 */
public static int totalScore() {
    int totalScore = 0;
    synchronized(runs) { // synch access with cleanup thread
        for(WeakReference<Score> scoreRef : runs) {
            final Score score = scoreRef.get();
            if(score != null) {
                totalScore += score.total;
            }
        }
    }
    return totalScore;
}

}

The idea is not to allow creating instances outside your factory method #getInstance(). The instances are tracked using WeakReferences to allow their Garbage Collection. The list is update by a service thread waiting on the reference queue. Hope this helps.