Фактически, мы имеем бесконечное число связей и свойств объекта, воссоздание которых не имеет, во-первых смысла, а во-вторых фактически не возможно.
В такие моменты к нам приходит на помощь абстракция. Абстракция – это отвлечение от несущественных деталей объекта в пользу более существенных.
Представим, что у нас есть кот. Как описать кота в программе?
Я могу придумать следующие отличительные свойства кота:
- У него есть длина усов
- Длина хвоста
- Длина от хвоста до усов
- Цвет шерсти
И вот я создаю класс в программе:
Фрагмент 1.48
class Cat
{
public int WhiskerLength;
public int TailLength;
public int Length;
public Color Color;
}
Сижу, пержу, смотрю вдаль и начинаю понимать, что суть программы не в моделировании общего кота, а в функционале. А кот – это лишь смысловая единица, через которую я описываю функционал моей программы.
И что, на самом деле, функционал программы заключается в том, что когда я на кота кликаю, они издаёт один из 4 заранее записанных звуков. И мы такие опа…
Оказывается, что кот – это абстракция от функционала генерации случайного звука из списка записанных, а также обработчик нажатия. И назвали мы эту сущность – кот. В итоге для этого нам понадобится, конечно же, другой класс.
В данном случае мы произвели абстракцию от того, что фактически делает код в сторону понятной сущности. Почему именно кот? Потому, что у нас на экране показывается кот, а приложение называется SweetCat. Это название логичное и очевидное.
Могли бы мы назвать получившийся класс как “RandomSoundOnClick”? Да, почему нет. Но таким образом мы бы пересказали внутренне устройство, и это было бы слишком буквально. Такая буквальность имеет смысл уровнем ниже. Но когда мы поднимемся выше, например, в код, который задаёт начальные данные на уровень, то там хотелось бы видеть нечто подобное:
Фрагмент 1.49
var cat = new Cat(listOfSounds, Color.Gray);
EventSystem.RegistClickHandler(cat);
Всем сразу понятно, что тут конфигурируют кота.
Грубо говоря то, что сейчас сделано – это абстракция для программиста. Абстракция от тонкостей реализации для понимания предназначения и глобального замысла в рамках всей программы и решаемой задачи.
Но также у нас есть части нашей системы, которые имеют свой взгляд, которому важны другие детали. Например, у нас уже появилась система обработки событий, которая принимает некий объект и регистрирует его в системе. Когда происходит событие, то объект об этом оповещается. Система используется многими модулями программы. Например, не только кот хочет знать, что произошло событие, но и условная картина в игровом пространстве, которая реагирует на клик по-своему.
Фрагмент 1.50
var picture = new Picture(image);
EventSystem.RegistClickHandler(picture);
Неужели системе событий придётся с каждым случаем работать уникально? По-своему с картинами и по-своему с котом? На самом деле нет. Мы можем создать другую абстракцию.
Системе обработки событий нет никакого дела до того картина это или кот. Об этом, кстати, говорит один из принципов проектирования, ISP – принцип разделения интерфейсов, суть которого в том, что сущности при работе с другими сущностями должны знать необходимый минимум. Для системы событий, конечно же, излишне знать о цвете кота.
Для такой системы нужен свой взгляд на вещи. В нашем случае через абстракцию “ОбработчикСобытияКлика”. И мы будем говорить, что системе событий нужен некий обработчик события клика, и что у нас есть класс кот и книга, которые являются обработчиками события клика.
Звучит просто? Это и является довольно простым концептом, который открывает много возможностей и опасностей. Мы уже поняли, как это выражать на русском языке, и, как вы смогли догадаться, тоже самое мы можем выразить в программе на языке C#. И дальше будет именно это.