Рубрики
Без рубрики

По принципу “Открыто-закрыто” (Развязка и абстракция)

Здесь я буду отслеживать абстракцию менеджера контактов, которую я отделял, аналогично… Помеченный java.

Здесь я буду отслеживать абстракцию менеджера контактов, которую я отделял, аналогично примеру в моем посте об интерфейсах. Цель этого состоит в том, чтобы достичь точки, когда у меня будет базовая программа, которая не нуждается в модификации для добавления новых функций, но вместо этого может быть расширена новыми классами в соответствии со вторым из принципов SOLID.

По мере роста программы важно следить за ее структурой и выявлять возможности для абстракции. Если класс получает еще несколько функций, вы можете обнаружить, например, что одно упоминание строкового имени поля становится обычной ссылкой и что стоит добавить строку в переменную или серию констант в класс.

Если это не важно, я буду использовать абстрактные методы без тел. Ниже приведен класс Contact из моей программы, который хранит данные и изменяет их.

Пример 1 – Контакт

public class Contact {

public String FirstName;
// plus five more fields

public Contact(String firstName // five more here too) {
   this.FirstName = firstName;
    // plus five more fields
}

public updateFirstName(firstName) {
    if (!firstName.matches(String.valueOf(ValidateInput.blankString))) {
        FirstName = firstName;
    }
}
// plus five more almost identical update methods
}

Здесь сразу же возникает пара проблем. Во-первых, у меня есть шесть методов, выполняющих одно и то же только с одной переменной.

Концепция абстракции : Повторение указывает на то, что есть место для абстракции, поэтому давайте обобщим эти методы.

Во-вторых, класс Contact отвечает как за сохранение, так и за изменение своего собственного состояния. Это большая ответственность за то, что должно быть компьютерным эквивалентом карточки с шестью строками на ней.

Это также означает, что “структура” программы на самом деле представляет собой просто серию неотделимых классов, поскольку Contact Manager полагается на Contact , когда сообщает ему об обновлении.

Последовательность абстрактно-ификационных

public class ContactManager {

private ConsoleIO consoleIO;
private ArrayList contactList;

public ContactManager(ConsoleIO consoleIO, ArrayList contactList) {
   this.consoleIO = consoleIO;
   this.contactList = contactList;
}

public void updateField(String value, Contact contact, int field) {
    if (!value.matches(String.valueOf(ValidateInput.blankString))) {
        switch (field) {
            case 1: contact.FirstName = value; break;
            case 2: contact.LastName = value; break;
            case 3: contact.Address = value; break;
            case 4: contact.PhoneNumber = value; break;
            case 5: contact.DOB = value; break;
            default: contact.Email = value; break;
        }
    }
}
// and a lot of other methods
}

И теперь Контакт – это просто

public class Contact {

public String FirstName;
// same as before, 5 more

public Contact(String firstName) {
   this.FirstName = firstName;
}
}

Гораздо лучше. Теперь шесть методов – это один, а класс Contact имеет длину 18 строк и несет исключительную ответственность за хранение информации.

Пример 2 – Консольный ввод-вывод

Примечание: Если вы не знаете об интерфейсах, прокрутите назад и посмотрите другой пост в моей серии абстракций.

Console IO – это мой класс для обработки ввода и вывода, в частности, в консоли.

Чтобы реализовать созданный мной интерфейс ввода-вывода, ConsoleIO понадобилось четыре метода:

  1. дисплей
  2. getStringInput Получить строку ввода
  3. getMenuInput Получить меню ввода
  4. подтвердите ввод

В моем классе ConsoleIO были необходимые четыре метода для реализации интерфейса ввода-вывода, но у него также были методы, которые проверяли ввод.

public class ConsoleIO implements InputOutput{

public ConsoleIO()

public void display()

public String getStringInput()

public int getMenuInput()

public String getInput()

public static Boolean validateInput()

public static Boolean validName()

public static Boolean validNumber()

public static Boolean validDOB()

public static Boolean validEmail()

public static Boolean isBlank()
}

То, что начиналось как один или два метода, выросло до шести, и этому классу никогда по-настоящему не нужно было знать правила для допустимого ввода. Если бы это была белая доска, я бы нарисовал большой круг вокруг всего с valid в нем (и этот последний тоже, достаточно близко).

Абстракционист

public class ConsoleIO implements InputOutput{

public ConsoleIO()

public void display(String message)

public String getStringInput()

public int getMenuInput()

public String getInput()
    // this method calls validation methods
}

Console IO возвращается к своим основным методам, и ниже у нас есть новый класс, который даже не нужно инициализировать, поскольку все статично.

public class ValidateInput {

public final static Pattern blankString = Pattern.compile("^$");

public static Boolean validateInput(){
    // this one calls the ones below as appropriate
}

public static Boolean validName()

public static Boolean validNumber()

public static Boolean validDOB()

public static Boolean validEmail()

public static Boolean isBlank()

}

Развязка

Становится намного проще смотреть на эти классы и рассказывать, что они делают. Консольный ввод-вывод не знает, что делает ввод допустимым, и ValidateInput не знает, откуда поступают входные данные или куда они возвращаются.

Концепция развязки: Если класс не предназначен для обработки других классов (например, Contact Manager handles Contact s), то он ничего не должен знать о том, как он работает. Чем меньше он знает, тем меньше он полагается на детали низкого уровня. Передача информации из Консольного ввода-вывода в Validate Input следует рассматривать как черный ящик, куда вводится ввод, происходят таинственные (см.: абстрактные) действия, а затем выводятся выходные данные.

Может показаться, что это не так уж много улучшений; что я только что перенес методы из класса 1 в класс 2 и что классу 1 все еще нужны методы класса 2. Однако значение заключается в том, что я могу поменять ConsoleIO на другой класс на основе интерфейса ввода-вывода, например ‘ WebIO ‘, и мне не нужно повторять методы проверки.

Концепция абстракции: Абстракция не должна иметь значения сейчас, ценность заключается в содействии будущим изменениям. Я освободил место для будущих занятий, но мне не нужно знать, как они работают.

Конечная Цель

Хотя эта программа еще не закончена, примеры, которые я привел, были базовыми изменениями, которые привели к постепенным улучшениям сейчас и значительно упростили будущие изменения.

Цель этой программы – достичь точки, когда каждый класс знает ровно столько, чтобы выполнять свою часть работы, чтобы я мог заменить любой класс другим, который следует соответствующему интерфейсу.

Что при этом достигается, так это максимальное пространство для расширения без необходимости предвидеть какую-либо конкретную функциональность. Используя это в Интернете? Замените ConsoleIO на новый Webio.

Оригинал: “https://dev.to/jimjule/on-the-open-closed-principle-decoupling-abstraction-2eok”