HTML Diff
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&lt;WebElement&gt; items = driver.findElements(By.cssSelector(".item")); logger.info("Found {} items", items.size());<p>Вариант нормальный, пока таких вызовов, ну, скажем, 7. Хотя уже неприятно и минусы такого подхода очевидны любому, кто хоть раз "слегка модифицировал свой код".</p>
10 List&lt;WebElement&gt; 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&lt;WebElement&gt; 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&lt;WebElement&gt; 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&lt;WebElement&gt; findElements(By var1) { List&lt;WebElement&gt; 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&lt;WebElement&gt; findElements(By var1) { List&lt;WebElement&gt; 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&lt;WebElement&gt; findElements(By var1) { List&lt;WebElement&gt; items = driver.findElements(var1); logger.info("Selector {}. Found {} elements", var1.toString(), items.size()); return items; }<p>Мы расширили в соответствии с нашей задачей. Вот и всё, можно юзать в тестах:</p>
19 public List&lt;WebElement&gt; findElements(By var1) { List&lt;WebElement&gt; 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&lt;WebElement&gt; items = driver.findElements(By.cssSelector("a")); // =&gt; Selector By.cssSelector: a. Found 48 elements<p>Паттерн хорош, если нужно навесить логирование, кэширование, ленивую инициализацию, контроль доступа к методам. В общем, если вы пишете код и вам очень хочется, чтобы была какая-то прослоечка с вашими фичами, один из вариантов - прокси.</p>
20 WebDriver driver = new LoggerWebDriver(); driver.get("http://google.com"); List&lt;WebElement&gt; items = driver.findElements(By.cssSelector("a")); // =&gt; Selector By.cssSelector: a. Found 48 elements<p>Паттерн хорош, если нужно навесить логирование, кэширование, ленивую инициализацию, контроль доступа к методам. В общем, если вы пишете код и вам очень хочется, чтобы была какая-то прослоечка с вашими фичами, один из вариантов - прокси.</p>
21 <p>Теперь, когда мы знаем на один паттерн больше, напомню, что<strong>когда в руке молоток, всё вокруг кажется гвоздями</strong>. Просто помните об этом.</p>
21 <p>Теперь, когда мы знаем на один паттерн больше, напомню, что<strong>когда в руке молоток, всё вокруг кажется гвоздями</strong>. Просто помните об этом.</p>
22  
22