Le patron Strategy est un patron comportemental du GoF qui permet de faire varier l'algorithme (i.e. le code) utilisé dans une classe.
⇛L'idée est d'utiliser un objet pour simplement fournir du code et de définir une interface commune à ces objets.
En d'autres termes, c'est que vous faîtes à chaque fois qu'une classe ou une méthode prend en paramètre une lambda.
Par exemple, dans l'API Java, la méthode de tri List<T>.sort(Comparator<? super T>) prend en paramètre le code permettant de comparer deux éléments.
record Credential(String login, String password) { ... }
class ConnexionHandler {
// ...
private boolean isSecured(Crendential credential){
if (!Pattern.compile("[a-z]+").matcher(credential.login()).matches()){
return false;
}
return credential.password().length()>=8;
}
public void connect(Credential credential) {
if (!isSecured(credential)){
...
}
}
}
On veut pouvoir faire évoluer la vérification des indentifiants en respectant le principe Open-Close.
Respecter le principe Open-Close, c'est pouvoir changer la façon de valider les identifiants simplement en rajoutant des classes mais sans modifier à chaque fois la classe ConnectionHandler.
Idéalement, on voudrait:
// ancien comportement var connectionHandler = new ConnectionHandler(); // nouveau comportement var connectionHandler2 = new ConnectionHandler( code de validation );
@FunctionalInterface
interface CredentialValidator {
boolean isSecure(Credential credential);
}
class ConnectionHandler {
private final static PasswordValidator DEFAULT_VALIDATOR = s -> {
if (!Pattern.compile("[a-z]+").matcher(credential.login()).matches()){
return false;
}
return credential.password().length()>=8;
}
private final CredentialValidator validator;
public void ConnectionHandler(){
this.validator = DEFAULT_VALIDATOR;
}
public void ConnectionHandler(CredentialValidator validator){
this.validator = Objects.requireNonNull(validator);
}
// ...
private boolean isSecured(Crendential cred){
return validator.isSecured(credential);
}
}
Le patron strategy pré-date l'introduction des lambdas en Java. Le principe était le même, on définissait une interface et l'on prenait un objet implémentant cette interface.
L'interface CredentialValidator est identique à Predicate<Credential>. Ici, on a fait le choix de nommer l'interface pour rendre le code plus accessible à des non-spécialistes des lambdas.