0 added
0 removed
Original
2026-01-01
Modified
2026-03-10
1
<p>Главная идея<strong>паттерна proxy</strong>(в русскоязычных изданиях его называют "заместитель") состоит в том, чтобы выдать для работы не реальный объект, а подмену, которая использует методы объекта и нашу логику, если мы такую добавили.</p>
1
<p>Главная идея<strong>паттерна proxy</strong>(в русскоязычных изданиях его называют "заместитель") состоит в том, чтобы выдать для работы не реальный объект, а подмену, которая использует методы объекта и нашу логику, если мы такую добавили.</p>
2
<h2>Как это делается</h2>
2
<h2>Как это делается</h2>
3
<p>1) Создаём интерфейс с публичными методами объекта, который хотим подменить. 2) Создаём класс, который: - реализует этот интерфейс; - имеет доступ к оригинальному объекту, чтобы вызывать его методы. 3) Добавляем в методы созданного класса свою логику.</p>
3
<p>1) Создаём интерфейс с публичными методами объекта, который хотим подменить. 2) Создаём класс, который: - реализует этот интерфейс; - имеет доступ к оригинальному объекту, чтобы вызывать его методы. 3) Добавляем в методы созданного класса свою логику.</p>
4
<h2>Практика</h2>
4
<h2>Практика</h2>
5
<p>На практике должно быть понятней. Дано: есть у нас<strong>WebDriver</strong>. И есть у него метод findElements(By by); Задача: мне очень сильно нужно логировать, сколько элементов было найдено по селектору.</p>
5
<p>На практике должно быть понятней. Дано: есть у нас<strong>WebDriver</strong>. И есть у него метод findElements(By by); Задача: мне очень сильно нужно логировать, сколько элементов было найдено по селектору.</p>
6
<p>Каждый раз, когда я вызываю метод:</p>
6
<p>Каждый раз, когда я вызываю метод:</p>
7
driver.findElements(By.cssSelector(".item"));<p>я хочу видеть в логах запись - сколько элементов было найдено.</p>
7
driver.findElements(By.cssSelector(".item"));<p>я хочу видеть в логах запись - сколько элементов было найдено.</p>
8
<h2>Решение 1. В лоб</h2>
8
<h2>Решение 1. В лоб</h2>
9
<p>Чего уж там: я его применял. Просто берём и при каждом вызове пишем, сколько было найдено:</p>
9
<p>Чего уж там: я его применял. Просто берём и при каждом вызове пишем, сколько было найдено:</p>
10
List<WebElement> items = driver.findElements(By.cssSelector(".item")); logger.info("Found {} items", items.size());<p>Вариант нормальный, пока таких вызовов, ну, скажем, 7. Хотя уже неприятно и минусы такого подхода очевидны любому, кто хоть раз "слегка модифицировал свой код".</p>
10
List<WebElement> items = driver.findElements(By.cssSelector(".item")); logger.info("Found {} items", items.size());<p>Вариант нормальный, пока таких вызовов, ну, скажем, 7. Хотя уже неприятно и минусы такого подхода очевидны любому, кто хоть раз "слегка модифицировал свой код".</p>
11
<h2>Решение 2. Используем прокси</h2>
11
<h2>Решение 2. Используем прокси</h2>
12
<p>WebDriver - интерфейс. Объявлены методы, но нет реализации. Реализацию содержат ChromeWebDriver, FirefoxWebDriver и т. д. Нам, в тестах, не обязательно работать с каким-то конкретным классом для хрома или сафари. Нужно только, чтобы класс имплементил интерфейс<strong>WebDriver</strong>. Это и сделаем.</p>
12
<p>WebDriver - интерфейс. Объявлены методы, но нет реализации. Реализацию содержат ChromeWebDriver, FirefoxWebDriver и т. д. Нам, в тестах, не обязательно работать с каким-то конкретным классом для хрома или сафари. Нужно только, чтобы класс имплементил интерфейс<strong>WebDriver</strong>. Это и сделаем.</p>
13
<p>Создаём интерфейс с публичными методами объекта, который хотим подменить. В нашем примере такой интерфейс уже есть -<strong>WebDriver</strong>. Создаём класс, который: - реализует этот интерфейс; - имеет доступ к оригинальному объекту, чтобы вызывать его методы.</p>
13
<p>Создаём интерфейс с публичными методами объекта, который хотим подменить. В нашем примере такой интерфейс уже есть -<strong>WebDriver</strong>. Создаём класс, который: - реализует этот интерфейс; - имеет доступ к оригинальному объекту, чтобы вызывать его методы.</p>
14
public class LoggerWebDriver implements WebDriver{ private WebDriver driver; public void get(String s) { } public List<WebElement> findElements(By by) { return null; } public WebElement findElement(By by) { return null; } //остальные методы отрезал для краткости }<p>Добавляем в методы созданного класса свою логику:</p>
14
public class LoggerWebDriver implements WebDriver{ private WebDriver driver; public void get(String s) { } public List<WebElement> findElements(By by) { return null; } public WebElement findElement(By by) { return null; } //остальные методы отрезал для краткости }<p>Добавляем в методы созданного класса свою логику:</p>
15
public class LoggerWebDriver implements WebDriver { private WebDriver driver; private final Logger logger = LogManager.getLogger(LoggerWebDriver.class); LoggerWebDriver() { //жёстких ограничений по конструктору нет. //В идеале, он(и) должны повторять конструкторы объекта. this.driver = new ChromeDriver(); } public void get(String var1) { driver.get(var1); } public List<WebElement> findElements(By var1) { List<WebElement> items = driver.findElements(var1); logger.info("Selector {}. Found {} elements", var1.toString(), items.size()); return items; } public WebElement findElement(By var1) { return driver.findElement(var1); } //остальные методы отрезал для краткости }<h2>Что произошло?</h2>
15
public class LoggerWebDriver implements WebDriver { private WebDriver driver; private final Logger logger = LogManager.getLogger(LoggerWebDriver.class); LoggerWebDriver() { //жёстких ограничений по конструктору нет. //В идеале, он(и) должны повторять конструкторы объекта. this.driver = new ChromeDriver(); } public void get(String var1) { driver.get(var1); } public List<WebElement> findElements(By var1) { List<WebElement> items = driver.findElements(var1); logger.info("Selector {}. Found {} elements", var1.toString(), items.size()); return items; } public WebElement findElement(By var1) { return driver.findElement(var1); } //остальные методы отрезал для краткости }<h2>Что произошло?</h2>
16
<p>В класс добавлен:</p>
16
<p>В класс добавлен:</p>
17
private WebDriver driver;<p>Это тот самый объект, который мы хотим подменить. Именно его методы мы будем вызывать дальше. Теперь, можно посмотреть, например, на метод:</p>
17
private WebDriver driver;<p>Это тот самый объект, который мы хотим подменить. Именно его методы мы будем вызывать дальше. Теперь, можно посмотреть, например, на метод:</p>
18
public void get(String var1) { driver.get(var1); }<p>Всё, что делает метод, - вызывает get() у настоящего драйвера. А вот метод:</p>
18
public void get(String var1) { driver.get(var1); }<p>Всё, что делает метод, - вызывает get() у настоящего драйвера. А вот метод:</p>
19
public List<WebElement> findElements(By var1) { List<WebElement> items = driver.findElements(var1); logger.info("Selector {}. Found {} elements", var1.toString(), items.size()); return items; }<p>Мы расширили в соответствии с нашей задачей. Вот и всё, можно юзать в тестах:</p>
19
public List<WebElement> findElements(By var1) { List<WebElement> items = driver.findElements(var1); logger.info("Selector {}. Found {} elements", var1.toString(), items.size()); return items; }<p>Мы расширили в соответствии с нашей задачей. Вот и всё, можно юзать в тестах:</p>
20
WebDriver driver = new LoggerWebDriver(); driver.get("http://google.com"); List<WebElement> items = driver.findElements(By.cssSelector("a")); // => Selector By.cssSelector: a. Found 48 elements<p>Паттерн хорош, если нужно навесить логирование, кэширование, ленивую инициализацию, контроль доступа к методам. В общем, если вы пишете код и вам очень хочется, чтобы была какая-то прослоечка с вашими фичами, один из вариантов - прокси.</p>
20
WebDriver driver = new LoggerWebDriver(); driver.get("http://google.com"); List<WebElement> items = driver.findElements(By.cssSelector("a")); // => Selector By.cssSelector: a. Found 48 elements<p>Паттерн хорош, если нужно навесить логирование, кэширование, ленивую инициализацию, контроль доступа к методам. В общем, если вы пишете код и вам очень хочется, чтобы была какая-то прослоечка с вашими фичами, один из вариантов - прокси.</p>
21
<p>Теперь, когда мы знаем на один паттерн больше, напомню, что<strong>когда в руке молоток, всё вокруг кажется гвоздями</strong>. Просто помните об этом.</p>
21
<p>Теперь, когда мы знаем на один паттерн больше, напомню, что<strong>когда в руке молоток, всё вокруг кажется гвоздями</strong>. Просто помните об этом.</p>
22
22