(Mentre questa domanda ha a che fare con un concreto dilemma del codice, è soprattutto su quale sia il modo migliore di progettare una funzione.)
Sto scrivendo un metodo che dovrebbe prendere due oggetti Color e trasformare gradualmente il primo Colore nel secondo, creando un'animazione. Il metodo sarà in una classe di utilità.
Il mio problema è che il colore è un oggetto immutabile. Ciò significa che non posso fare color.setRGB
o color.setBlue
all'interno di un ciclo nel metodo.
Quello che posso fare, è creare un'istanza di un nuovo colore e restituirlo dal metodo. Ma poi non potrò gradatamente cambiare il colore.
Quindi ho pensato a tre possibili soluzioni:
1- Il codice client include la chiamata al metodo all'interno di un ciclo. Ad esempio:
int duration = 1500; // duration of the animation in milliseconds
int steps = 20; // how many 'cycles' the animation will take
for(int i=0; i<steps; i++) color = transformColor(color, targetColor, duration, steps);
E il metodo sarebbe simile a questo:
Color transformColor(Color original, Color target, int duration, int steps){
int redDiff = target.getRed() - original.getRed();
int redAddition = redDiff / steps;
int newRed = original.getRed() + redAddition;
// same for green and blue ..
Thread.sleep(duration / STEPS); // exception handling omitted
return new Color(newRed, newGreen, newBlue);
}
Lo svantaggio di questo approccio è che il codice client deve "fare parte del lavoro del metodo" e includere un ciclo for
. Il metodo non funziona completamente a proprio, cosa che non mi piace.
2- Crea una sottoclasse Color
mutabile con metodi come setRed
e passa gli oggetti di questa classe in transformColor
. Quindi potrebbe essere simile a questo:
void transformColor(MutableColor original, Color target, int duration){
final int STEPS = 20;
int redDiff = target.getRed() - original.getRed();
int redAddition = redDiff / steps;
int newRed = original.getRed() + redAddition;
// same for green and blue ..
for(int i=0; i<STEPS; i++){
original.setRed(original.getRed() + redAddition);
// same for green and blue ..
Thread.sleep(duration / STEPS); // exception handling omitted
}
}
Quindi il codice chiamante di solito sarebbe simile a questo:
// The method will usually transform colors of JComponents
JComponent someComponent = ... ;
// setting the Color in JComponent to be a MutableColor
Color mutableColor = new MutableColor(someComponent.getForeground());
someComponent.setForeground(mutableColor);
// later, transforming the Color in the JComponent
transformColor((MutableColor)someComponent.getForeground(), new Color(200,100,150), 2000);
Lo svantaggio è: la necessità di creare una nuova classe MutableColor
e anche la necessità di eseguire il casting.
3- Passa nel metodo l'oggetto mutabile reale che contiene il colore. Quindi il metodo potrebbe eseguire object.setColor
o simili ogni iterazione del ciclo.
Due svantaggi:
A- Non così elegante. Passare nell'oggetto che trattiene il colore solo per trasformare il colore sembra innaturale.
B- Mentre la maggior parte delle volte questo metodo verrà usato per trasformare i colori all'interno di JComponent
oggetti, anche altri tipi di oggetti potrebbero avere colori. Quindi il metodo dovrebbe essere sovraccaricato per ricevere altri tipi, o ricevere Object
s e avere instanceof
controlli all'interno. Non ottimale.
In questo momento, penso che mi piaccia la soluzione n. 2, più della soluzione n. 1 e della soluzione n. 3. Tuttavia mi piacerebbe sentire le vostre opinioni e suggerimenti su questo.