Всем привет. Этот урок является частью цикла статей о паттернах проектирования. Пример кода расположен по ссылке.
Singleton
Паттерн Singleton используется в тех случаях, в которых вы хотите ограничить экземпляр класса только одним объектом.
Класс не должен требовать параметры для построения. Если создание класса требует значительных ресурсов, то Singleton является подходящим решением. Довольно удобно, когда объект создается до того, когда его нужно использовать в других классах.
Паттерн Null object
Идея состоит в том, чтобы сделать код более простым и безопасным, допуская проверки на предмет равенства объекта null:
1 2 3 |
if (someVariable != null) { // Do something with someVariable } |
Null object позволяет смело вызывать созданные методы проверки на предмет равенства null без использования исключения NullRefferenceException. Этот паттерн очень хорошо сочетается с Singleton, где объектом, равным null, может быть сам объект Singleton.
Пример
Наиболее частое использование Singleton – ограничение WebDriver до одного экземпляра объекта на весь проект.
1 2 3 4 5 6 7 8 9 10 11 12 |
private static IWebDriver webDriver; public static IWebDriver WebDriver { get { if (webDriver == null) { webDriver = new FirefoxDriver(); } return webDriver; } } |
Я собираюсь показать несколько иной пример, где Singleton используется вместе с паттерном Null object. NullWebElement реализует интерфейс IWebElement, поэтому он должен реализовать все методы и свойства, определенные интерфейсом. Это сделано в строках 4 – 21. Свойства возвращают некоторые значений, но не нулевые! Методы ничего не делают. Singleton реализуется в строках 23 - 36. Если объект Singleton не равен null, то только в этом случае создается объект.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
public class NullWebElement : IWebElement { private const string nullWebElement = "NullWebElement"; public bool Displayed { get { return false; } } public bool Enabled { get { return false; } } public Point Location { get { return new Point(0, 0); } } public bool Selected { get { return false; } } public Size Size { get { return new Size(0, 0); } } public string TagName { get { return nullWebElement; } } public string Text { get { return nullWebElement; } } public void Clear() { } public void Click() { } public string GetAttribute(string attributeName) { return nullWebElement; } public string GetCssValue(string propertyName) { return nullWebElement; } public void SendKeys(string text) { } public void Submit() { } public IWebElement FindElement(By by) { return this; } public ReadOnlyCollection<IWebElement> FindElements(By by) { return new ReadOnlyCollection<IWebElement>(new List<IWebElement>()); } private NullWebElement() { } private static NullWebElement instance; public static NullWebElement NULL { get { if (instance == null) { instance = new NullWebElement(); } return instance; } } } |
Есть два основных преимущества кода выше. Первое преимущество само использование паттерна Null object. Вы можете найти элемент, который еще не существует, и вызвать его методы в тестах и при этом они не упадут.
1 2 3 4 5 6 7 8 9 10 |
IWebElement element = null; try { element = webDriver.FindElement(By.CssSelector("notExisting")); } catch { element = NullWebElement.NULL; } element.Click(); |
На проверку равенства null выделяется какое-то время. И может возникнуть логичный вопрос,- стоит ли вообще использовать такую проверку. Мое мнение следующее, – делать проверку нужно. Реальная выгода заключается в том, что вы будете иметь только один неудачный тест вместо проваленного рана всех тестов.
Второе преимущество приходит от паттерна Singleton. Вы можете легко сравнить любой элемент с конструкцией NullWebElement.NULL. Скорее всего, вы найдете элемент и безопасно его используете благодаря паттерну Null object.
1 2 3 4 |
if (element == NullWebElement.NULL) { Console.WriteLine("Element not found!"); } |
Таким образом, Singleton обязателен для изучения. Null object в комбинации с Singleton может уменьшить количество кода, особенно при написании больших проектов.