J'ai mis du temps à comprendre ce réponse et ce qu'elle signifie vraiment. Quelques exemples devraient rendre les choses plus claires.
Proxy
d'abord :
public interface Authorization {
String getToken();
}
Et :
// goes to the DB and gets a token for example
public class DBAuthorization implements Authorization {
@Override
public String getToken() {
return "DB-Token";
}
}
Et il y a un appel de ce Authorization
une assez stupide :
class Caller {
void authenticatedUserAction(Authorization authorization) {
System.out.println("doing some action with : " + authorization.getToken());
}
}
Rien d'inhabituel jusqu'à présent, non ? Obtenir un jeton d'un certain service, utiliser ce jeton. Maintenant, il faut ajouter une autre exigence à l'image, ajouter la journalisation : c'est-à-dire enregistrer le jeton à chaque fois. C'est simple dans ce cas, il suffit de créer un fichier Proxy
:
public class LoggingDBAuthorization implements Authorization {
private final DBAuthorization dbAuthorization = new DBAuthorization();
@Override
public String getToken() {
String token = dbAuthorization.getToken();
System.out.println("Got token : " + token);
return token;
}
}
Comment l'utiliserions-nous ?
public static void main(String[] args) {
LoggingDBAuthorization loggingDBAuthorization = new LoggingDBAuthorization();
Caller caller = new Caller();
caller.authenticatedUserAction(loggingDBAuthorization);
}
Remarquez que LoggingDBAuthorization
tient une instance de DBAuthorization
. Les deux sites LoggingDBAuthorization
y DBAuthorization
mettre en œuvre Authorization
.
- Un proxy contient une implémentation concrète (
DBAuthorization
) de l'interface de base ( Authorization
). En d'autres termes, un Proxy sait exactement ce qui est proxié.
Decorator
:
Ça commence à peu près de la même façon que Proxy
avec une interface :
public interface JobSeeker {
int interviewScore();
}
et une mise en œuvre de celle-ci :
class Newbie implements JobSeeker {
@Override
public int interviewScore() {
return 10;
}
}
Et maintenant nous voulons ajouter un candidat plus expérimenté, qui ajoute son score d'entretien à celui d'un autre candidat. JobSeeker
:
@RequiredArgsConstructor
public class TwoYearsInTheIndustry implements JobSeeker {
private final JobSeeker jobSeeker;
@Override
public int interviewScore() {
return jobSeeker.interviewScore() + 20;
}
}
Remarquez comment j'ai dit que plus celui d'un autre JobSeeker , pas Newbie
. A Decorator
ne sait pas exactement ce qu'il décore, il ne connaît que le contrat de cette instance décorée (il connaît les éléments suivants JobSeeker
). Notez ici que ce n'est pas comme un Proxy
qui, en revanche, sait exactement ce qu'il décore.
Vous pouvez vous demander s'il y a réellement une différence entre les deux modèles de conception dans ce cas ? Et si nous essayions d'écrire le Decorator
en tant que Proxy
?
public class TwoYearsInTheIndustry implements JobSeeker {
private final Newbie newbie = new Newbie();
@Override
public int interviewScore() {
return newbie.interviewScore() + 20;
}
}
Cette option est tout à fait envisageable et souligne à quel point ces motifs sont proches ; ils sont néanmoins destinés à des scénarios différents, comme expliqué dans les autres réponses.