Co prawda można zrobić generatory na wiele sposobów i wcale użycie yield nie jest wymagane, ale chciałem zobaczyć czy uda mi się takie coś popełnić w Java'ie ;-)
Idea jest taka by pisać tylko generator (który będzie w klasie niestety). Np. generator liczb od 0 do ilości wywołań (zakładając, że jest ich mniej niż maksymalna wartość int'a) może wyglądać tak:
public class Counter extends Generator<Integer> {
@Override public void generate() {
int i=0;
while (true) {
yield(i++);
}
}
}
znów generator, który będzie generował ciąg 1,2,3,1,2,3,1,2,3 i tak dalej z powtarzaniem się 1,2,3 będzie wyglądał tak:
public class Counter123 extends Generator<Integer> {
@Override public void generate() {
while (true) {
yield(1);
yield(2);
yield(3);
}
}
}A generator, który będzie generował poszczególne znaki ze Stringa tak:
public class LettersFromString extends Generator<String> {
private String str;
public LettersFromString(String str) {
this.str = str;
}
@Override public void generate() {
int idx = 0;
while (idx<str.length()) yield(""+str.charAt(idx++));
}
}Użycie generatora zaś będzie wyglądało tak, że najpierw go stworzymy, a później będziemy dostawać wartości przezeń generowane po zawołaniu next(). Jeśli wartości nie będzie to dostaniemy null.
Czyli przy generatorze:
public class OnceGenerator extends Generator<String> {
@Override public void generate() {
yield("Test");
}
}Przy pierwszym zawołaniu next() dostaniemy "Test", a przy drugim null.
Ogólna idea jest taka by pisząc generator myśleć tylko o generowaniu kolejnej wartości, a nie o całym cięciu naszego algorytmu generowania na jakieś kawałki.
Ludzie myślą jednowątkowo i generator powinien być pisany tak jakby to był jeden wątek.
No i stworzyłem portfora ;-) który pozwala na tworzenie takich generatorów ;-)
public abstract class Generator<T> {
private T value;
private Object lock = new Object();
boolean available = false;
public Generator() {
this(null);
}
public Generator(T val) {
this.value = val;
new Thread(new Runnable() {
@Override public void run() {
synchronized (lock) {
generate();
available = true;
}
}
}).start();
}
public abstract void generate();
public void yield(T val) {
this.value = val;
this.available = true;
try {
lock.notify();
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public T next() {
synchronized (lock) {
while (!available) {
try {
lock.wait();
} catch (InterruptedException ie) {
}
}
T val = this.value;
this.value = null;
this.available = false;
lock.notify();
return val;
}
}
}Który to potfór pozwala na tworzenie generatorów jak w ECMAScript6 ;-)
Teraz się zastanawiam czy można by było stworzyć takie generatory bez wątków i na razie nie wiem.
Podobne postybeta
Przepływ sterowany danymi - A takie Java'owe coś ;-)
Generator programów
"CPUInfo" w Java :-)
wait() i notify()/notifyAll() - najbardziej nierozumiane metody klasy Object ;-)
Modale dobre - confirm dla Androida :-)
Brak komentarzy:
Prześlij komentarz