La classe base delle anatre é Duck, una classe astratta che ha due dati membro che sono poi le due strategie dell'anatra: il modo di volare e il modo di emettere un verso.
Notiamo che, per essere utilizzabile, un anatra reale dovrà definire le due strategie, in modo che possano essere coerentemente invocati i metodi fly() e quack() su di essa. Il metodo swim é comune a tutte le implementazioni, e quindi viene definito in Duck.
package hf.strategy;
public abstract class Duck {
protected FlyBehavior flyBehavior;
protected QuackBehavior quackBehavior;
public Duck() {
}
public void setFlyBehavior (FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
public void fly() {
flyBehavior.fly();
}
public void quack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("All ducks float, even decoys!");
}
}
La definizione di un'anatra reale richiederà la specificazione delle strategie adottate. Vediamo ad esempio la classe MallardDuck:
package hf.strategy;
public class MallardDuck extends Duck {
public MallardDuck() {
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
}
Strategie
Restano ora da definire le strategie. Al top della gerarchia di una strategia ci sarà un'interfaccia, che dichiara il metodo che viene richiesto. Qui vediamo la strategia di volo:
package hf.strategy;
public interface FlyBehavior {
public void fly();
}
E qui la strategia di starnazzamento:
package hf.strategy;
public interface QuackBehavior {
public void quack();
}
Una classe reale utilizzerà una implementazione coerente con i suoi scopi delle strategie richieste. MallardDuck richiedeva queste:
package hf.strategy;
public class Quack implements QuackBehavior {
public void quack() {
System.out.println("Quack");
}
}
// ---
package hf.strategy;
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("I'm flying!!");
}
}
Nessun commento:
Posta un commento