Jest kilka algorytmów, które lecą po kolei na danych. Jak 1 algorytm znajdzie roziwązanie to cały proces nie leci już dalej tylko wyrzucane jest rozwiązanie z algorytmu 1. Jak algorytm 1 nie znajdzie rozwiążania to leci algorytm 2. Jak algorymt 2 znajdzie rozwiązanie to cały proces już nie leci dalej tylko wyrzucane jest rozwiązanie z algorytmu 2. itd. To jest commander? strategia? a może flyweight?
Chain of responsibility.
Michał Sikora napisał(a):
Chain of responsibility.
i serio warto robić, tak, że i-ty algorytm wskazuje i+1 a i+1 na i+2 ?
alg1.setNext(alg2);
alg2.setNext(alg3);
//...
alg1.process();
a nie lepiej zrobić commander, który zawiera listę algorytmów i leci z nimi po kolei?
commander.add(alg1);
commander.add(alg2);
// ...
commander.process();
Zależy, co chcesz osiągnąć. To, co opisałeś w pierwszym poście, to chain of responsibility i command pattern nijak tu nie pomaga. Realizować możesz na różne sposoby. Nie musisz mieć w algorytmie, żeby jeden wskazywał na drugi. Możesz mieć osobną klasę, która się tym zajmie. Możesz też to zrobić np. na strumieniach.
To co opisałeś ja napisałbym mniej więcej tak:
interface SomeProblem
{
Result solve(Inputs input);
};
class Alg1 implements SomeProblem
{
private SomeProblem fallback;
public Alg1(SomeProblem fallback);
...
};
...
class NoSolution implements SomeProblem
{
public override Result solve(Inputs input) {
throw new NoSolutionFoundException(input);
}
};
SomeProblem solver = new Alg1(new Alg2(new Alg3(new Alg4(new NoSolution()))));
Result result = solver.solve(input);
Chodzi o to, żeby poszczególne algorytmy były jak najbardziej od siebie odseparowane, oraz żeby nie było tej okropnej drabinki if-ów.
Dodanie nowego algorytmu w tym przypadku jest proste jak konstrukcja cepa.
To chyba zależy od tego, czy biznesowo algorytmy
o sobie wiedzą:
public class Classloader{
private final Optional<Classloader> parentClassloader;
public Optional<Class<?>> loadClass(String name) {
return loadClassFormResources(name)
.orElseGet(() -> parentClassloader.loadClass(name));
}
}
czy:
public class TimberOrderService {
private final PriorityQueue<Sawmill> sawmills;
public Optional<TimberOrder> requestTimber(TimberRequest timberRequest) {
return sawmills.stream()
.map(sawmill -> sawmill.order(timberOrder))
.filter(TimberOrder::isSuccessful)
.findFirst();
}
}
A gdybym jechał do końca z tymi algorytmami bez względu na ich wynik oraz te algorytmy nie miałyby hierarchi (mogą być w dowolnej kolejności) to będzie jaki wzorzec? Composite?
czyli:
// ...
AlgorithmsComposite<String, String> algCompot = new AlgorithmsComposite<>();
algCompot.add(new Alg1()).add(new Alg2()).add(new Alg3())
.setInput(input)
.getSolutions();
// ...
public class AlgorithmsComposite<IN, OUT> {
private List<Alg<IN, OUT>> algorithmsToRun = new LinkedList<>();
private IN input;
private List<OUT> solutions;
public add(Alg<IN, OUT> alg) {
algorithmsToRun.put(alg);
return this;
}
public setInput(Input input) {
this.input = input;
return this;
}
public List<OUT> getSolutions() {
return algorithmsToRun.stream()
.map(alg -> alg.apply(input))
.collect(Collectors.toLists());
}
}
public interface Alg<IN, OUT> extends Function<IN, OUT> {
}
public class Alg1 implements Alg<String, String> {
@Override
public String apply(String input) {
// ... do sth and return String
}
}
public class Alg2 implements Alg<String, String> {
@Override
public String apply(String input) {
// ... do sth and return String
}
}
public class Alg3 implements Alg<String, String> {
@Override
public String apply(String input) {
// ... do sth and return String
}
}
do przyjęcia takie coś?