Потребовалось время, чтобы понять этот ответ и то, что он на самом деле означает. Несколько примеров должны прояснить ситуацию.
Proxy
первый:
public interface Authorization {
String getToken();
}
И :
// goes to the DB and gets a token for example
public class DBAuthorization implements Authorization {
@Override
public String getToken() {
return "DB-Token";
}
}
И у этого есть вызывающий Authorization
, довольно тупой:
class Caller {
void authenticatedUserAction(Authorization authorization) {
System.out.println("doing some action with : " + authorization.getToken());
}
}
Пока что ничего необычного, правда? Получите токен от определенной службы, используйте этот токен. Теперь появляется еще одно требование к изображению, добавление регистрации: это означает, что каждый раз регистрирует токен. В этом случае все просто, просто создайте 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;
}
}
Как нам это использовать?
public static void main(String[] args) {
LoggingDBAuthorization loggingDBAuthorization = new LoggingDBAuthorization();
Caller caller = new Caller();
caller.authenticatedUserAction(loggingDBAuthorization);
}
Обратите внимание, что LoggingDBAuthorization
содержит экземпляр DBAuthorization
. Как LoggingDBAuthorization
и DBAuthorization
реализовать Authorization
.
- Прокси-сервер будет содержать некоторую конкретную реализацию (
DBAuthorization
) базового интерфейса ( Authorization
). Другими словами, Прокси-сервер точно знает , что проксируется.
Decorator
:
Все начинается примерно так же, как Proxy
и с интерфейсом:
public interface JobSeeker {
int interviewScore();
}
и его реализация:
class Newbie implements JobSeeker {
@Override
public int interviewScore() {
return 10;
}
}
А теперь мы хотим добавить более опытного кандидата, который добавляет свой балл на собеседовании и баллы другого JobSeeker
:
@RequiredArgsConstructor
public class TwoYearsInTheIndustry implements JobSeeker {
private final JobSeeker jobSeeker;
@Override
public int interviewScore() {
return jobSeeker.interviewScore() + 20;
}
}
Обратите внимание, как я сказал это плюс одно от другого ищущего работу , а не Newbie
. A Decorator
не знает точно, что он украшает, он знает только контракт этого украшенного экземпляра (он знает JobSeeker
). Обратите внимание, что это не похоже на Proxy
; который, напротив, точно знает, что украшает.
Вы можете спросить, есть ли на самом деле разница между двумя шаблонами проектирования в этом случае? Что, если бы мы попытались записать Decorator
как Proxy
?
public class TwoYearsInTheIndustry implements JobSeeker {
private final Newbie newbie = new Newbie();
@Override
public int interviewScore() {
return newbie.interviewScore() + 20;
}
}
Это определенно вариант, который подчеркивает, насколько близки эти модели; они по-прежнему предназначены для разных сценариев, как описано в других ответах.