Design patterns Nascondere i dettagli di implementazione della strategia


Esempio

Una linea guida molto comune nel design orientato agli oggetti è "il meno possibile ma quanto necessario". Ciò vale anche per il modello di strategia: in genere è consigliabile nascondere i dettagli di implementazione, ad esempio quali classi implementano effettivamente le strategie.

Per strategie semplici che non dipendono da parametri esterni, l'approccio più comune consiste nel rendere la classe di implementazione stessa privata (classi nidificate) o package-private e nell'esporre un'istanza attraverso un campo statico di una classe pubblica:

public class Animal {

  private static class AgeComparator implements Comparator<Animal> {
    public int compare(Animal a, Animal b) {
      return a.age() - b.age();
    }
  }

  // Note that this field has the generic type Comparator<Animal>, *not*
  // Animal.AgeComparator!
  public static final Comparator<Animal> AGE_COMPARATOR = new AgeComparator();

  private final int age;

  Animal(int age) {
    this.age = age;
  }

  public int age() {
    return age;
  }

}

List<Animal> myList = new LinkedList<>();
myList.add(new Animal(10));
myList.add(new Animal(5));
myList.add(new Animal(7));
myList.add(new Animal(9));

Collections.sort(
  myList,
  Animal.AGE_COMPARATOR
);

Il campo pubblico Animal.AGE_COMPARATOR definisce una strategia che può quindi essere utilizzata in metodi come Collections.sort , ma non richiede all'utente di sapere nulla sulla sua implementazione, nemmeno sulla classe di implementazione.

Se preferisci, puoi usare una classe anonima:

public class Animal {

  public static final Comparator<Animal> AGE_COMPARATOR = new Comparator<Animal> {
    public int compare(Animal a, Animal b) {
      return a.age() - b.age();
    }
  };

  // other members...
}

Se la strategia è un po 'più complessa e richiede parametri, è molto comune utilizzare metodi di factory static come Collections.reverseOrder(Comparator<T>) . Il tipo di ritorno del metodo non dovrebbe esporre dettagli di implementazione, ad esempio reverseOrder() è implementato come

public static <T> Comparator<T> reverseOrder(Comparator<T> cmp) {
  // (Irrelevant lines left out.)
  return new ReverseComparator2<>(cmp);
}