PDA

View Full Version : [JAVA]pochi if-else,velocità, e leggibilità...e anche patterns


MEMon
04-03-2009, 11:45
Apro questo thread con l'intentzione di racchiudere un pò di "trucchetti" per migliorare la qualità del nostro codice.

Per iniziare, un problema che mi si presenta spesso è quello di dover eseguire un metodo a seconda del valore che assume una determinata variabile.
Ad esempio:

public void execute(int type){
switch(type){
case A: actionA();return;
case B: actionB();return;
...
}
}

Il problema è che uso una bella catena di case, e in questo modo valuto la catena ogni volta che mi serve utilizzare il metodo,penso sia lento.

Di solito risolvo creando una classe per ogni azione che devo compiere:


class A extends C{

...

public void execute(){
System.out.println("action A");
}
}

class B extends C{

...

public void execute(){
System.out.println("action B");
}
}

abstract class C{

...

public void execute();
}

class Executor{

private C c;

public Executor(int type){
c=valute(type);
}

private C valute(int type){
switch(type){
case A: return new A();
case B return new B();
}
}

public void execute(){
c.execute();
}

}


...
...
Executor e=new Executor(A);
e.execute();
...
...



In questo modo ho rimosso il controllo durante l'esecuzione spostandolo a "monte" e secondo me è anche più leggibile, però la catena di case rimane, e ho dovuto creare tante classi quante sono le azioni strade che posso intraprendere.
C'è modo per eliminare anche lo switch?
Secondo voi è una buona soluzione?

shinya
04-03-2009, 12:30
Spostare "new A()", "new B()" alla chiamata del costruttore di Executor?

Executor e = new Executor(new A());
e.execute();

^TiGeRShArK^
04-03-2009, 12:54
io farei cosi'....

class A implements C {

...

public void execute() {
System.out.println("action A");
}
}

class B implements C {

...

public void execute() {
System.out.println("action B");
}
}

public interface C {
public void execute();
}

class Executor{

private C myAction;

public Executor(C myAction){
this.myAction = myAction;
}

public void execute(){
myAction.execute();
}

}


...
...
A a = new A();
Executor executor = new Executor(a);
executor.execute();

anche se l'executor potrebbe pure non essere necessario....

~FullSyst3m~
04-03-2009, 13:14
io farei cosi'....

class A implements C {

...

public void execute() {
System.out.println("action A");
}
}

class B implements C {

...

public void execute() {
System.out.println("action B");
}
}

public interface C {
public void execute();
}

class Executor{

private C myAction;

public Executor(C myAction){
this.myAction = myAction;
}

public void execute(){
myAction.execute();
}

}


...
...
A a = new A();
Executor executor = new Executor(a);
e.execute();

anche se l'executor potrebbe pure non essere necessario....

Non dovrebbe essere executor.execute()?

^TiGeRShArK^
04-03-2009, 13:17
Non dovrebbe essere executor.execute()?
yes..
m'ero perso un pezzo...

^TiGeRShArK^
04-03-2009, 13:21
mmmm...
rileggendo forse ho capito cosa intendeva fare...
se ho capito bene basterebbe aggiungere al mio codice un array di action (o una mappa a seconda dei valori che deve assumere la variabile) e richiamare semplicemente map[variable].execute();
ho capito bene stavolta o ancora mi sfugge qualcosa? :stordita:

^TiGeRShArK^
04-03-2009, 13:25
tradotto in codice:

class A implements Action {

...

public void execute() {
System.out.println("action A");
}
}

class B implements Action {

...

public void execute() {
System.out.println("action B");
}
}

public interface Action {
public void execute();
}

class Executor{

private Action[] myActions;

public Executor(Action[] myActions){
this.myActions = myActions;
}

public void execute(int val){
myActions[val].execute();
}

}

int val = ???;
...
...
Action[] myActions = new Actions[2];
myActions[0] = new A();
myActions[1] = new B();
Executor executor = new Executor(myActions);
executor.execute(val);

MEMon
04-03-2009, 17:09
tradotto in codice:

class A implements Action {

...

public void execute() {
System.out.println("action A");
}
}

class B implements Action {

...

public void execute() {
System.out.println("action B");
}
}

public interface Action {
public void execute();
}

class Executor{

private Action[] myActions;

public Executor(Action[] myActions){
this.myActions = myActions;
}

public void execute(int val){
myActions[val].execute();
}

}

int val = ???;
...
...
Action[] myActions = new Actions[2];
myActions[0] = new A();
myActions[1] = new B();
Executor executor = new Executor(myActions);
executor.execute(val);

Esatto questo è quello che volevo vedere.
La domanda sorge spontanea ora, è meglio il "mio" metodo che fa usa di switch(o if) o quello proposta da te che istanzia oggetti senza avere la sicurezza che poi vengano effettivamente usati?
Ho paura che a parte il fatto che non vengano usati if-else non porti altri vantaggi, perchè sicuramente non è più veloce visto che deve istanziare tanti oggetti quante sono le varie azioni che devo fare, ne di spazio per lo stesso motivo.
Sono ovviamente mie supposizioni campate in aria, cosa ne pensi?

MEMon
04-03-2009, 17:36
Se banalmente devo eseguire del codice solo se vera una determinata condizione, esempio:

...
if(cond){
esegui();
}
...

E' possibile anche in questo caso eliminare il controllo condizionale?


Inoltre sempre nel medisimo caso, è meglio come scritto sopra, o così:

...
if(!cond) return;
esegui();
...

Ci sono differenza a livello prestazionale? Il compilatore interpreta allo stesso modo?

^TiGeRShArK^
04-03-2009, 19:20
Esatto questo è quello che volevo vedere.
La domanda sorge spontanea ora, è meglio il "mio" metodo che fa usa di switch(o if) o quello proposta da te che istanzia oggetti senza avere la sicurezza che poi vengano effettivamente usati?
Ho paura che a parte il fatto che non vengano usati if-else non porti altri vantaggi, perchè sicuramente non è più veloce visto che deve istanziare tanti oggetti quante sono le varie azioni che devo fare, ne di spazio per lo stesso motivo.
Sono ovviamente mie supposizioni campate in aria, cosa ne pensi?

a livello di velocità di esecuzione pura dovrebbe essere + veloce il metodo con l'array di action dato che non viene creato nessun branch, a livello di spreco di memoria credo che siamo lì con la catena di if se abbiamo una media di esecuzione piuttosto simile per le varie action, dato che resteranno comunque nel garbage collector.
Inoltre con l'array crei solo un'istanza di ogni action, invece con l'if crei una nuova istanza della action corrente per ogni esecuzione e questo peggiora sia la velocità di esecuzione che l'occupazione di memoria prima del passaggio del GC.
comunque tutto questo in teoria...
per vedere l'effettiva differenza prestazionale l'unica cosa è provare con un profiler il codice in modo da vedere velocità di esecuzione e occupazione di memoria.

^TiGeRShArK^
04-03-2009, 19:28
Se banalmente devo eseguire del codice solo se vera una determinata condizione, esempio:

...
if(cond){
esegui();
}
...

E' possibile anche in questo caso eliminare il controllo condizionale?


Inoltre sempre nel medisimo caso, è meglio come scritto sopra, o così:

...
if(!cond) return;
esegui();
...

Ci sono differenza a livello prestazionale? Il compilatore interpreta allo stesso modo?
si può usare la stessa tecnica se la condizione è un'intero o un qualsiasi oggetto.
Nel caso di un oggetto qualsiasi si ha qualcosa del genere:

String cond = ???;

....

Map<String, Action> map = new HashMap<String, Action>();
map.add("pippo", new Pippo());
map.add("pluto", new Pluto());
map.add("topolino", new Topolino());
map.get(cond).execute();

invece per quanto riguarda scrivere:

if (!cond)
return;
execute();

if(cond)
execute();

dovrebbe essere uguale *in teoria*

dupa
04-03-2009, 20:35
Apro questo thread con l'intentzione di racchiudere un pò di "trucchetti" per migliorare la qualità del nostro codice.

Per iniziare, un problema che mi si presenta spesso è quello di dover eseguire un metodo a seconda del valore che assume una determinata variabile.

CUT

In questo modo ho rimosso il controllo durante l'esecuzione spostandolo a "monte" e secondo me è anche più leggibile, però la catena di case rimane, e ho dovuto creare tante classi quante sono le azioni strade che posso intraprendere.
C'è modo per eliminare anche lo switch?
Secondo voi è una buona soluzione?

sinceramente mi sembra una soluzione da "ufficio complicazione affari semplici".

comunque partendo dal problema di partenza:

public void execute(int type){

Io non ho mai avuto in vita mia una funzione alla quale passo un type per farle eseguire cose diverse....

non vedo perchè il codice che chiama execute, non dovrebbe chiamare direttamente il metodo che vuole eseguire, piuttosto che passare da questo "wrapper".

MEMon
04-03-2009, 20:41
sinceramente mi sembra una soluzione da "ufficio complicazione affari semplici".

comunque partendo dal problema di partenza:

public void execute(int type){

Io non ho mai avuto in vita mia una funzione alla quale passo un type per farle eseguire cose diverse....

non vedo perchè il codice che chiama execute, non dovrebbe chiamare direttamente il metodo che vuole eseguire, piuttosto che passare da questo "wrapper".
Bhe probabilmente perche te hai sempre fatto così:

...
A a=new A();
B b=new B();
if(type==INT_A){
a.eseguie();
}
else if(type==INT_B){
b.esegui();
}
...

Che ha tutti i problemi, poca leggibilità, decisione a runtime ecc ecc.

MEMon
04-03-2009, 20:42
si può usare la stessa tecnica se la condizione è un'intero o un qualsiasi oggetto.
Nel caso di un oggetto qualsiasi si ha qualcosa del genere:

String cond = ???;

....

Map<String, Action> map = new HashMap<String, Action>();
map.add("pippo", new Pippo());
map.add("pluto", new Pluto());
map.add("topolino", new Topolino());
map.get(cond).execute();

invece per quanto riguarda scrivere:

if (!cond)
return;
execute();

if(cond)
execute();

dovrebbe essere uguale *in teoria*
Però, mica male così, ma viene usato davvero per eliminare gli if?

^TiGeRShArK^
04-03-2009, 20:45
Però, mica male così, ma viene usato davvero per eliminare gli if?

si, array e mappe sono usati comunemente, insieme al polimorfismo e a qualche altro strumento, per eliminare gli if.

^TiGeRShArK^
04-03-2009, 20:46
sinceramente mi sembra una soluzione da "ufficio complicazione affari semplici".

comunque partendo dal problema di partenza:

public void execute(int type){

Io non ho mai avuto in vita mia una funzione alla quale passo un type per farle eseguire cose diverse....

non vedo perchè il codice che chiama execute, non dovrebbe chiamare direttamente il metodo che vuole eseguire, piuttosto che passare da questo "wrapper".
infatti nel mio primo post ho specificato che l'executor generalmente non è necessario, ma non so nel suo caso se ha qualche motivo particolare per esistere...

MEMon
04-03-2009, 20:49
Ma nel tuo prima post non avevi capito quello che chiedevo, è ovvio che se so a priori di usare un metodo di A allora non serve l'esecutore, ma la situazione non è quella :)

La situazione è che in base a una condizione o al valore di una variabile devo fare cose diverse.

dupa
04-03-2009, 20:49
Bhe probabilmente perche te hai sempre fatto così:

...
A a=new A();
B b=new B();
if(type==INT_A){
a.eseguie();
}
else if(type==INT_B){
b.esegui();
}
...

Che ha tutti i problemi, poca leggibilità, decisione a runtime ecc ecc.

per sta cosa che hai scritto al max si usa il polimorfismo.
ma cmq anche il polimorfismo deve una logica di base.....

se hai super-classe Shape, estesa da Square, Circle

chiamerai

square.computeArea()
circle.computeArea()

ecc.

MEMon
04-03-2009, 20:50
per sta cosa che hai scritto al max si usa il polimorfismo.

E fammi vedere come lo usi il polimorfismo per sta cosa che ho scritto.

^TiGeRShArK^
04-03-2009, 20:51
Ma nel tuo prima post non avevi capito quello che chiedevo, è ovvio che se so a priori di usare un metodo di A allora non serve l'esecutore, ma la situazione non è quella :)

La situazione è che in base a una condizione o al valore di una variabile devo fare cose diverse.
ma in concreto perchè ha un valore diverso questa variabile?
da cosa dipende?

dupa
04-03-2009, 20:52
poca leggibilità

comunque riguardo la poca leggibilità, quello che tu hai scritto nel primo codice:

Executor e=new Executor(A);
e.execute();


il metodo "execute" mi sembra ben poco chiaro riguardo cosa sta per eseguire

dupa
04-03-2009, 20:54
E fammi vedere come lo usi il polimorfismo per sta cosa che ho scritto.

Non è che i design pattern o la OOP la devi sempre applicare a prescindere.. io ti posso fare un esempio dove il polimorfismo serve..

hai tante Shape, shape è astratta, definisce metodo computeArea... iteri su lista SHape, senza sapere di che tipo sono.. e fai la sommatoria delle aree.

questo è un esempio "utile" di polimorfismo

nel tuo caso, come dicevo mi sembra complicazione affari semplici.

MEMon
04-03-2009, 21:10
ma in concreto perchè ha un valore diverso questa variabile?
da cosa dipende?

Ma niente era un'esempio, posso fartelo anche pratico se vuoi.
Ad esempio ho un una serie di eventi che si possono verificare nel tempo.
Ogni evento è caratterizzato dal tempo in cui si verificherà, e dall'azione che farà quando si verifica.
Gli eventi sono scelti dall'utente attravero la GUI(esempio).


abstract class EventoIndefinito{

final public static INT_A=0;
final public static INT_B=1;

public int time;

public EventoIndefinito(int time){
this.time=time;
}

public static EventoIndefinito specifica(int type,int time){
switch(type){
case INT_A: return new EventoA(time);
case INT_B: return new EventoB(time);
}
}

public void azione(int currentTime);
}

class EventoA extends EventoIndefinito{

public EventoA(int time){
super(time);
}

public void azione(int currentTime){
if(this.time==currentTime) System.out.println("A");
}
}

class EventoB extends EventoIndefinito{

public EventoB(int time){
super(time);
}

public void azione(int currentTime){
if(this.time==currentTime) System.out.println("B");
}
}



Vector eventi=new Vector();


//esecuzione (type e time provengono dalla GUI)
...
eventi.addElement(EventoIndefinito.specifica(type,time));
...
for(int i=0;i<eventi.size();i++){
eventi.elementAt(i).azione(currentTime);
}
...


Questo è un esempio banale ma comunque ce ne sono tanti.

MEMon
04-03-2009, 21:12
comunque riguardo la poca leggibilità, quello che tu hai scritto nel primo codice:

Executor e=new Executor(A);
e.execute();


il metodo "execute" mi sembra ben poco chiaro riguardo cosa sta per eseguire

In realtà no perchè è proprio per quel motivo che è più leggibile.
Insomma sai che sta eseguendo l'azione di un oggetto di tipo C, e te ne vuoi fregare di sapere che e cosa fa.
Poi mi pare scontato che non mischierai pere con mele, si tratta dell'esecuzione della stessa cosa ma che differisce in qualcosa.

MEMon
04-03-2009, 21:13
Non è che i design pattern o la OOP la devi sempre applicare a prescindere.. io ti posso fare un esempio dove il polimorfismo serve..

hai tante Shape, shape è astratta, definisce metodo computeArea... iteri su lista SHape, senza sapere di che tipo sono.. e fai la sommatoria delle aree.

questo è un esempio "utile" di polimorfismo

nel tuo caso, come dicevo mi sembra complicazione affari semplici.
Il mio caso diventa subito utile se ci pensi un attimo, ovvio che il primo post era solo un esempio, e comunque già lì è utile a meno che te non voglia vedere una struttura condizionale enorme.

^TiGeRShArK^
04-03-2009, 21:23
Ma niente era un'esempio, posso fartelo anche pratico se vuoi.
Ad esempio ho un una serie di eventi che si possono verificare nel tempo.
Ogni evento è caratterizzato dal tempo in cui si verificherà, e dall'azione che farà quando si verifica.
Gli eventi sono scelti dall'utente attravero la GUI(esempio).


abstract class EventoIndefinito{

final public static INT_A=0;
final public static INT_B=1;

public int time;

public EventoIndefinito(int time){
this.time=time;
}

public static EventoIndefinito specifica(int type,int time){
switch(type){
case INT_A: return new EventoA(time);
case INT_B: return new EventoB(time);
}
}

public void azione(int currentTime);
}

class EventoA extends EventoIndefinito{

public EventoA(int time){
super(time);
}

public void azione(int currentTime){
if(this.time==currentTime) System.out.println("A");
}
}

class EventoB extends EventoIndefinito{

public EventoB(int time){
super(time);
}

public void azione(int currentTime){
if(this.time==currentTime) System.out.println("B");
}
}



Vector eventi=new Vector();


//esecuzione (type e time provengono dalla GUI)
...
eventi.addElement(EventoIndefinito.specifica(type,time));
...
for(int i=0;i<eventi.size();i++){
eventi.elementAt(i).azione(currentTime);
}
...


Questo è un esempio banale ma comunque ce ne sono tanti.
e anche in questo caso non potresti semplicemente fare:

public class Event {
private int time;

public void Event(int time) {
this.time = time;
}

public void action (int time) { ; }

protected void isExecutionNeeded(int time) {
if (this.time == time) {
return true;
} else {
return false;
}
}
}

class EventOne extends Event {

public EventOne(int time) {
super(time);
}

public void action(int currentTime) {
if(isExecutionNeeded(currentTime)) {
System.out.println("A");
}
}
}

class EventTwo extends Event {

public EventTwo(int time) {
super(time);
}

public void action(int currentTime) {
if(isExecutionNeeded(currentTime)) {
System.out.println("B");
}
}
}


Event[] events = new Event[2];
events[0] = new EventOne(time1);
events[1] = new EventTwo(time2);
for (Event e : events) {
e.action(currentTime);
}



EDIT: che cazz di shortcut da tastiera invia il post? :mbe:

dupa
04-03-2009, 21:24
Il mio caso diventa subito utile se ci pensi un attimo, ovvio che il primo post era solo un esempio, e comunque già lì è utile a meno che te non voglia vedere una struttura condizionale enorme.

sinceramnte non so quanto sia "grande" la tua applicazione, comunque per piccole applicazioni non mi sembra decisamente il caso di andare a definire classi Evento, classi Azione... o roba del genere.

in una logica di sviluppo agile, se la tua applicazione è piccola partirei con uno stile più semplice possibile... quando la tua applicazione crescerà farai un refactoring se la vecchia logica non sarà più adeguata.

poi vedi un po tu

MEMon
04-03-2009, 21:25
e anche in questo caso non potresti semplicemente fare:

public interface Event {

public void action (int time);
}

int[] events = new int[10];
//inizializzazione



se lo dici probabilmente si :D
come prosegue poi?

MEMon
04-03-2009, 21:27
sinceramnte non so quanto sia "grande" la tua applicazione, comunque per piccole applicazioni non mi sembra decisamente il caso di andare a definire classi Evento, classi Azione... o roba del genere.

in una logica di sviluppo agile, se la tua applicazione è piccola partirei con uno stile più semplice possibile... quando la tua applicazione crescerà farai un refactoring se la vecchia logica non sarà più adeguata.

poi vedi un po tu

Hai ragione, il senso del post era comunque scoprire trucchetti vari e metodologie usate per migliorare un pò il classico stile "semplice" che poi si sposeran bene con progetti più ampi.

^TiGeRShArK^
04-03-2009, 21:40
se lo dici probabilmente si :D
come prosegue poi?

non so che cazz di tasti ho spinto e mi ha inviato il post.. :mbe:
cmq ho editato il messaggio precedente.
Io un meccanismo di tipo executor + actions l'ho usato ad esempio in un branch di diamonds quando dovevamo scrivere un interprete per un linguaggio di scripting che doveva usare il customer per gestire transizioni di scena, animazioni & cazzi & mazzi (che alla fine non abbiamo mai implementato totalmente) ma perchè scrivevo tutto il codice dei vari comandi in un apposita classe con quel nome e tramite la reflection la caricavo al runtime e la eseguivo valorizzando correttamente i vari eventuali parametri che saltavano fuori dal parsing del file che doveva produrre il customer.
Cmq credo anch'io che è sempre bene far nascere cose del genere dal refactoring, inserirle troppo spesso va contro il principio YAGNI. :p

MEMon
04-03-2009, 21:47
non so che cazz di tasti ho spinto e mi ha inviato il post.. :mbe:
cmq ho editato il messaggio precedente.
Io un meccanismo di tipo executor + actions l'ho usato ad esempio in un branch di diamonds quando dovevamo scrivere un interprete per un linguaggio di scripting che doveva usare il customer per gestire transizioni di scena, animazioni & cazzi & mazzi (che alla fine non abbiamo mai implementato totalmente) ma perchè scrivevo tutto il codice dei vari comandi in un apposita classe con quel nome e tramite la reflection la caricavo al runtime e la eseguivo valorizzando correttamente i vari eventuali parametri che saltavano fuori dal parsing del file che doveva produrre il customer.
Cmq credo anch'io che è sempre bene far nascere cose del genere dal refactoring, inserirle troppo spesso va contro il principio YAGNI. :p

Ma nel tuo esempio però verrano eseguiti entrambi i metodi sia di A che di B.
Nel mio esempio vengono inseriti in un Vettore(ma potevo anche usare un array) gli oggetti ma a seconda di una variabile(o di una condizione).


Cos'è il principio YAGNI? :p

dupa
04-03-2009, 22:01
Ma nel tuo esempio però verrano eseguiti entrambi i metodi sia di A che di B.
Nel mio esempio vengono inseriti in un Vettore(ma potevo anche usare un array) gli oggetti ma a seconda di una variabile(o di una condizione).


Cos'è il principio YAGNI? :p

http://en.wikipedia.org/wiki/You_Ain%27t_Gonna_Need_It

^TiGeRShArK^
04-03-2009, 22:13
Ma nel tuo esempio però verrano eseguiti entrambi i metodi sia di A che di B.
Nel mio esempio vengono inseriti in un Vettore(ma potevo anche usare un array) gli oggetti ma a seconda di una variabile(o di una condizione).


Cos'è il principio YAGNI? :p

allora si poteva semplicemente fare così al posto di usare un vettore:

Map<Event, boolean> events = new HashMap<Event, boolean>();
events.put(new EventOne, condition);
events.put(new EventTwo, condition);
for (Map.Entry<Event, boolean> e : events.entrySet()) {
if (e.getValue())
e.getKey().action(currentTime);
}


senza cambiare la struttura che avevo scritto...
anche se sono sicuro che c'è un modo + furbo di implementare il tutto solo che finchè non capisco per bene il caso specifico sinceramente mi sfugge :p
quanto a yagni mi sa che t'ha risposto già dupa :p

MEMon
04-03-2009, 22:26
Immaginati di avere un pannello con 2 checkbox(type) , un campo di testo per inserire dei numeri(time) e un pulsante OK.
Ogni volta che premi ok devi creare un Evento da inserire in una "lista", che successivamente verrà scorsa per lanciare gli eventi.

^TiGeRShArK^
04-03-2009, 22:47
Immaginati di avere un pannello con 2 checkbox(type) , un campo di testo per inserire dei numeri(time) e un pulsante OK.
Ogni volta che premi ok devi creare un Evento da inserire in una "lista", che successivamente verrà scorsa per lanciare gli eventi.

ok, e fin qua ci sono...
i due checkbox sono il tipo di evento?
se si basta aggiungere alla lista il tipo di evento corrispondente al checkbox, in pratica qualcosa del genere:

if (checkbox1) {
events.add(new EventOne(time);
}
if (checkbox2) {
events.add(new EventTwo(time));
}

oppure semplicemente metti un eventHandler sul cambiamento del checkbox che inserisce in una variabile l'evento da aggiungere:

private currentEvent;
.....
checkBox1ChangeListener(object sender, EventArgs e) {
currentEvent = new EventOne();
}

checkBox2ChangeListener(object sender, EventArgs e) {
currentEvent = new EventTwo();
}

buttonOkListener(object sender, EventArgs e) {
currentEvent.setTime(textboxTime.getText();
events.add(currentEvent);
}

ovviamente i listeners me li sono inventati perchè è da un bel pò che non tocco swing e non mi ricordo tutti i suoi metodi, comunque ad occhio mi pare che fili il discorso. :p
ovviamente alla fine ti basta fare:

while (true) {
for (Event e : events) {
e.action();
}
}

passargli il currentTime mi sa che è inutile dato che all'interno dell'action puoi fare così:

if (this.executionTime == System.currentTimeMillis()) {
//do wathever you want
}

comunque in effetti piuttosto che fare un loop che controlli continuamente se eseguire qualche evento mi sa che è MOOOLTO + efficiente utilizzare la classe Timer :p
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Timer.html

MEMon
04-03-2009, 22:53
Ok i checkbox erano l'esempio meno consono :p
Cerca di venirmi incontro, lo so bene che si può fare come dici, ma quello è il "classico modo semplice" di fare le cose.

Se ad esempio hai un oggetto simile ad una ListBox che ti da l'indice dell'elemento selezionato(una cosa tipo getSelectedtIndex() ), e quello sarà il tuo type.
Ora ho capito che te in quel caso useresti le mappe vero?

Ovvio che si può fare così eh:

if(selectedIndex==INT_A){
events.addElement(new EventoA(time));
}
else if(selectedIndex==INT_B){
events.addElement(new EventoB(time));
}


Era per fare le cose più belle...

MEMon
04-03-2009, 22:57
comunque in effetti piuttosto che fare un loop che controlli continuamente se eseguire qualche evento mi sa che è MOOOLTO + efficiente utilizzare la classe Timer :p
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Timer.html
Ma non scendere nei particolariiiiiiiiiiiiiiiii, era un esempio, ho messo i "..." quel codice può essere ovunque, se dovessi davvero fare una cosa del genere lo metterei in un Timer ma non ci interessa...

dierre
06-03-2009, 13:59
tradotto in codice:

[...]
int val = ???;
...
...
Action[] myActions = new Actions[2];
myActions[0] = new A();
myActions[1] = new B();
Executor executor = new Executor(myActions);
executor.execute(val);


Ciao, scusate se arrivo in ritardo, quindi se la domanda è già stata fatta mi scuso. Però mi domandavo se fare una cosa del genere rispettasse davvero le richieste iniziali.
Tu così hai in effetti eliminato lo switch, però non hai istanziato memoria anche per oggetti che potrebbero essere non necessari? (visto che inizializzi l'array ma quale classe usare dipende dalla condizione)

Non è più veloce eliminare del tutto lo switch e passare al costruttore di executor direttamente l'oggetto?

MEMon
06-03-2009, 16:02
Infatti glielo ho fatto notare.

Passare direttamente l'oggetto no perchè altrimenti non rispetta le richiesta iniziali, ovvero dover eseguire cose divere a seconda di una variabile o banalmente una condizione.

dierre
06-03-2009, 16:19
Infatti glielo ho fatto notare.

Passare direttamente l'oggetto no perchè altrimenti non rispetta le richiesta iniziali, ovvero dover eseguire cose divere a seconda di una variabile o banalmente una condizione.

Ah quindi l'executor può ricevere solo la condizione?

MEMon
06-03-2009, 16:48
Può ricevere quello che vuoi, se riesci in modo diverso.

dierre
06-03-2009, 17:11
Infatti glielo ho fatto notare.

Passare direttamente l'oggetto no perchè altrimenti non rispetta le richiesta iniziali, ovvero dover eseguire cose divere a seconda di una variabile o banalmente una condizione.

Può ricevere quello che vuoi, se riesci in modo diverso.

Decidiamoci però :D, se può ricevere quello che vuole perché non un oggetto?

MEMon
06-03-2009, 17:12
Perchè come fai a sapere quale oggetto dargli?

dierre
06-03-2009, 17:15
Perchè come fai a sapere quale oggetto dargli?

ho detto una stronzata infatti :D Scusami.