Главная страница
Навигация по странице:

  • Структурированный код

  • Обертывание структурированного кода

  • Обертывание непереносимого кода

  • Обертывание существующих классов

  • Повторное использование объектов

  • Объектно-ориентированный подход. Объектно_ориентированный_подход. Объектно ориентированный подход Мэтт Вайсфельд 5е международное издание ббк 32. 973. 2018


    Скачать 5.43 Mb.
    НазваниеОбъектно ориентированный подход Мэтт Вайсфельд 5е международное издание ббк 32. 973. 2018
    АнкорОбъектно-ориентированный подход
    Дата31.03.2023
    Размер5.43 Mb.
    Формат файлаpdf
    Имя файлаОбъектно_ориентированный_подход.pdf
    ТипДокументы
    #1028905
    страница15 из 25
    1   ...   11   12   13   14   15   16   17   18   ...   25
    132
    это программирование. Под этим я подразумеваю, что хороший программист понимает основы логики программирования и испытывает страсть к написанию кода.
    Вы часто будете встречать объявления о найме программистов, обладающих на- бором определенных навыков, скажем, знающих определенный язык программи- рования, например Java. Я четко осознаю, что той или иной организации в трудную минуту вполне может потребоваться опытный Java-программист, но если говорить о долгосрочной перспективе, то я бы предпочел сосредоточить внимание на най- ме программиста, имеющего большой опыт в области программирования и спо- собного быстро учиться и приспосабливаться к новым технологиям. Некоторые из моих коллег не всегда соглашаются с этим; тем не менее я считаю, что при найме следует больше смотреть на то, чему потенциальный работник способен научиться, нежели на то, что он уже знает. Такая составляющая, как страсть к на- писанию кода, крайне важна, ведь она гарантирует, что работник будет постоян- но исследовать новые технологии и методологии разработки.
    Структурированный код
    Несмотря на то что по поводу основ логики программирования возможны дебаты, как я уже подчеркивал, фундаментальными объектно-ориентированными кон- цепциями являются инкапсуляции, наследование, полиморфизм и композиция.
    В большинстве учебников, которые я видел, в качестве базовых концепций струк- турного программирования указываются последовательность, условия и итерации.
    Последовательность является базовой концепцией потому, что представляется логичным начинать сверху и следовать вниз. Для меня суть структурного про- граммирования заключается в условиях и итерациях, которые я называю, соот- ветственно, операторами if и циклами.
    Взгляните на приведенный далее Java-код, который начинает с
    0
    и выполняет цикл десять раз, выводя значение, если оно равняется
    5
    :
    class MainApplication {
    public static void main(String args[]) {
    int x = 0;
    while (x <= 10) {
    if (x==5) System.out.println("x = " + x);
    x++;
    }
    }
    }

    133
    Объектные.обертки. .
    Несмотря на то что это объектно-ориентированный язык, код, располагающий- ся внутри основного метода, является структурированным. Присутствуют все три базовые концепции структурного программирования: последовательность,
    условия и итерации.
    Такую составляющую, как последовательность, легко идентифицировать, по- скольку первой выполняется строка int x = 0;
    Когда выполнение этой строки завершается, выполняется следующая строка:
    while (x <= 10) {
    И так далее. Одним словом, это проверенный подход в виде нисходящего про- граммирования: начать с первой строки, выполнить ее, а затем перейти к следу- ющей.
    В этом коде также содержится условие как часть оператора if
    :
    if (x==5)
    И наконец, цикл дополняет структурированное трио:
    while (x <= 10) {
    }
    Вообще-то цикл while тоже содержит условие:
    (x <= 10)
    Вы можете написать довольно большое количество кода, руководствуясь лишь тремя этими концепциями. Фактически понятие обертки в структурном про- граммировании в основном такое же, что и в объектно-ориентированном. При структурном проектировании в качестве оберток для кода используются функ- ции (как, например, основной метод в рассмотренном примере), а при объектно- ориентированном проектировании обертками для кода выступают объекты и методы.
    Обертывание структурированного кода
    Хотя определение атрибутов считается написанием кода (например, создание целочисленной переменной), поведения объектов располагаются внутри мето- дов. И в этих методах сосредоточена основная логика кода.
    Взгляните на рис. 6.3. Как вы можете видеть, объект содержит методы, а они, в свою очередь, включают код, который может быть любым, начиная с объяв- лений переменных и заканчивая условиями и циклами.

    Глава.6..Проектирование.с.использованием.объектов
    134
    Рис. 6.3. Обертывание.структурированного.кода
    Рассмотрим простой пример, в котором мы осуществим обертывание функцио- нальности, обеспечивающей сложение. В данном случае мы создадим метод с именем add
    , который примет два целочисленных параметра и возвратит их сумму:
    class SomeMath {
    public int add(int a, int b) {
    return a + b;
    }
    }
    Как вы можете видеть, структурированный код, используемый для выполнения сложения (
    a+b
    ), обернут в метод add
    . Хотя это простой пример, в нем показано все, что касается обертывания структурированного кода. Таким образом, когда пользователь захочет использовать данный метод, ему потребуется лишь подпись этого метода, как показано далее:
    public class TestMath {
    public static void main(String[] args) {
    int x = 0;
    SomeMath math = new SomeMath();
    x = math.add(1,2);

    135
    Объектные.обертки. .
    System.out.println("x = " + x);
    }
    }
    И наконец, взглянем на еще одну функциональность, которая немного интерес- нее и сложнее. Допустим, нам понадобилось включить метод для вычисления значения числа Фибоначчи. Тогда мы можем добавить такой метод:
    public static int fib(int n) {
    if (n < 2) {
    return n;
    } else {
    return fib(n-1)+fib(n-2);
    }
    }
    Самое главное здесь — показать, что у нас имеется объектно-ориентированный метод, который содержит (обертывает собой) структурированный код, посколь- ку метод fib содержит условия, рекурсию и т. д. И как уже отмечалось, в обертки также можно заключать существующий унаследованный код.
    Обертывание непереносимого кода
    Объектные обертки также могут использоваться для сокрытия непереносимого
    (или нативного) кода. Концепция, в принципе, будет аналогичной, однако в данном случае суть заключается в том, чтобы взять код, выполнение которого возможно только на одной платформе (или немногих платформах), и инкапсу- лировать его в методе с обеспечением простого интерфейса для программистов, которые будут использовать этот код.
    Возьмем, к примеру, задачу подачи сигнала. На платформе Windows мы можем обеспечить подачу сигнала с помощью приведенного далее кода:
    System.out.println("\007");
    Вместо того чтобы вынуждать программистов запоминать код (или искать его), вы можете предусмотреть класс с именем
    Sound
    , содержащий метод beep
    , как показано далее:
    class Sound {
    public void beep() {
    System.out.println("\007");
    }
    }

    Глава.6..Проектирование.с.использованием.объектов
    136
    Теперь вместо того чтобы запоминать код для обеспечения подачи сигнала, программисты смогут использовать этот класс и вызывать метод beep
    :
    public class TestBeep {
    public static void main(String[] args) {
    Sound mySound = new Sound();
    mySound.beep();
    }
    }
    Так программистам будет проще работать. Кроме того, вы сможете расширить функциональность класса, включив в него другие методы для генерирования сигналов. Пожалуй, более важно то, что при работе кода на платформе, не яв- ляющейся Windows, интерфейс для пользователей останется прежним. Корот- ко говоря, команде, которая будет создавать код для класса
    Sound
    , придется иметь дело с изменением платформы. Для программистов, использующих этот класс в своих приложениях, изменение не создаст никаких проблем, поскольку они по-прежнему смогут вызывать метод beep
    Обертывание существующих классов
    Хотя необходимость обертывать унаследованный структурированный или даже непереносимый код в тот или иной новый (объектно-ориентированный) класс может показаться резонной, необходимость обертывать существующие классы уже не настолько очевидна. Кроме того, есть много причин для того, чтобы создавать обертки для существующих (объектно-ориентированных) классов.
    Разработчики программного обеспечения часто применяют код, написанный кем-то другим. Это может быть код, приобретенный у поставщика или даже написанный людьми из той же организации. Во многих случаях оказывается, что код нельзя изменить. Возможно, из-за того, что человек, написавший код, больше не работает в организации либо поставщик не может предоставить па- кеты обновлений и т. д. Именно в таких ситуациях проявляется истинная мощь оберток.
    Идея заключается в том, чтобы взять существующий класс и изменить его реа- лизацию или интерфейс, обернув его в новый класс, — точно так же, как мы делали это со структурированным и непереносимым кодом. Разница здесь со- стоит в том, что вместо того чтобы придать коду объектно-ориентированное
    «обличье», мы изменяем его реализацию или интерфейс.
    Зачем нам это может потребоваться? Что ж, ответ заключается как в реализации, так и в интерфейсе.

    137
    Резюме. .
    Вспомните пример с базой данных, который мы использовали в главе 2. Наша цель состояла в обеспечении одинакового интерфейса для разработчиков неза- висимо от того, какую базу данных они будут использовать. Фактически если бы нам потребовалось обеспечить поддержку другой базы данных, то наша цель осталась бы прежней — сделать переход на новую базу данных прозрачным для пользователей (см. рис. 2.3).
    Кроме того, вспомните, как мы рассматривали вопрос создания промежуточно- го программного обеспечения для предоставления интерфейса между объекта- ми и реляционными базами данных. Нам как разработчикам требуется исполь- зовать объекты. Таким образом, понадобится функциональность, которая позволит нам сохранять объекты в базе данных. Мы не хотим, чтобы нам при- шлось писать SQL-код для каждой объектной транзакции, осуществляемой при работе с реляционной базой данных. Вот где мы можем считать промежуточное программное обеспечение оберткой. При этом доступно много продуктов для объектно-реляционного отображения.
    В принципе, для меня идеальным примером парадигмы «интерфейс/реализа- ция» является исследование, которое мы проводили в примере с электростан- цией в главе 2 (см. рис. 2.1). В данном случае у нас есть возможность изменить
    (обернуть) и то и другое: мы можем изменить интерфейс, сменив электрическую розетку, и можем изменить реализацию, сменив электростанцию.
    Обертки довольно широко используются при разработке программного обе- спечения, причем с позиции не только разработчиков, но и поставщиков. Оберт- ки — это важный инструмент при создании программных систем.
    Резюме
    В этой главе был рассмотрен процесс проектирования полных систем. Важно отметить, что объектно-ориентированный и структурированный код не явля- ются взаимоисключающими. Более того, вы не сможете создавать объекты без использования структурированного кода. Таким образом, при создании объ- ектно-ориентированных систем в процессе проектирования вы также будете использовать структурные методики.
    Объектные обертки применяются для инкапсуляции функциональности многих типов, которая может варьироваться от традиционного структурированного
    (унаследованного) и объектно-ориентированного (классы) кода до неперено- симого (нативного) кода. Основное назначение объектных оберток — обеспе- чивать согласованные интерфейсы для программистов, использующих соот- ветствующий код.
    В последующих главах мы подробнее исследуем взаимоотношения между клас- сами. В главе 7 рассматриваются концепции наследования и композиции, а также то, как они соотносятся друг с другом.

    Глава.6..Проектирование.с.использованием.объектов
    138
    Ссылки
    ‰
    Скотт Амблер, «Введение в объектно-ориентированную технологию»
    (The Object Primer). — 3-е изд. — Кембридж, Соединенное Королевство:
    Cambridge University Press, 2004.
    ‰
    Стив Макконнелл, «Совершенный код: практическое руководство по раз- работке программного обеспечения» (Code Complete: A Practical Handbook of Software Construction). — 2-е изд. — Редмонд, штат Вашингтон: Microsoft
    Press, 2004.
    ‰
    Стивен Гилберт и Билл Маккарти, «Объектно-ориентированное проектиро- вание на Java» (Object-Oriented Design in Java). — Беркли, штат Калифорния:
    The Waite Group Press (Pearson Education), 1998.
    ‰
    Джейми Яворски, «Платформа Java 2 в действии» (Java 2 Platform
    Unleashed). — Индианаполис, штат Индиана: Sams Publishing, 1999.
    ‰
    Джейми Яворски, «Руководство разработчика на Java 1.1» (Java 1.1 Developers
    Guide). — Индианаполис, штат Индиана: Sams Publishing, 1997.
    ‰
    Р. Вирфс-Брок, Б. Вилкерсон и Л. Вейнер, «Проектирование объектно-ори- ентированного программного обеспечения» (Designing Object-Oriented
    Software). — Аппер Сэддл Ривер, штат Нью-Джерси: Prentice-Hall, 1997.
    ‰
    Мэтт Вайсфельд и Джон Киккоцци, статья «Разработка программного обе- спечения рабочей группой» (Software by Committee) // Project Management, том 5, номер 1: с. 30–36, сентябрь 1999.

    Глава 7
    НАСЛЕДОВАНИЕ И КОМПОЗИЦИЯ
    Наследование и композиция играют главные роли в проектировании объектно- ориентированных систем. Фактически многие из наиболее сложных и интересных проектных решений сводятся к выбору между наследованием и композицией.
    С годами эти решения становились намного интереснее по мере того, как раз- вивались методики объектно-ориентированного проектирования. Пожалуй, наиболее любопытные дебаты ведутся вокруг наследования. Хотя наследова- ние — это одна из фундаментальных концепций объектно-ориентированной разработки (язык программирования должен поддерживать наследование для того, чтобы считаться объектно-ориентированным), некоторые программисты вообще отказываются от наследования, выполняя проектирование только с по- мощью композиции.
    Чаще можно встретить применение наследования интерфейсов, а не прямое наследование поведений (реализация против наследования). Наследование чаще применяется для данных/моделей, в то время как реализация — для по- ведений.
    Несмотря на это, как наследование, так и композиция представляют собой ме- ханизмы повторного использования. Наследование, как видно из его названия, подразумевает получение по наследству атрибутов и поведений от других клас- сов. При этом имеет место настоящее отношение «родительский класс / дочер- ний класс». Дочерний класс (или подкласс) наследует напрямую от родитель- ского класса (или суперкласса).
    Композиция, как тоже видно из названия, подразумевает создание объектов с использованием других объектов. В этой главе мы исследуем явные и тонкие различия между наследованием и композицией. В первую очередь мы рассмо- трим, когда именно и какой механизм следует использовать.
    Повторное использование объектов
    Пожалуй, главная причина существования наследования и композиции — по- вторное использование объектов. Коротко говоря, вы можете создавать клас-

    Глава.7..Наследование.и.композиция
    140
    сы (которые в конечном счете станут объектами), применяя другие классы посредством наследования и композиции. Ведь эти механизмы фактически являются единственными способами повторного использования ранее создан- ных классов.
    Наследование представляет отношение «является экземпляром», рассмотренное в главе 1. Например, собака является экземпляром млекопитающего.
    Композиция подразумевает использование других классов для создания более сложных классов, то есть для осуществления своего рода сборки. При этом нет никаких отношений «родительский класс / дочерний класс». По сути, сложные объекты состоят из других объектов. Композиция представляет отношение «со- держит как часть». Например, автомобиль содержит как часть двигатель.
    Двигатель и автомобиль — отдельные, потенциально самостоятельные объекты.
    Однако автомобиль является сложным объектом, который включает в себя (со- держит как часть) такой объект, как двигатель. Кроме того, дочерний объект сам может состоять из других объектов; например, двигатель может включать в себя цилиндры. При этом двигатель содержит как часть цилиндр, которых на самом деле несколько.
    Когда объектно-ориентированные технологии только начали получать широкое распространение, наследование часто оказывалось первым, к чему программи- сты прибегали при проектировании объектно-ориентированных систем. Воз- можность единожды спроектировать класс, а затем наследовать от него функ- циональность считалась одним из главных преимуществ использования объектно-ориентированных технологий.
    Однако в дальнейшем слава наследования немного померкла. На самом деле даже во время первых дискуссий использование наследования как такового ставилось под сомнение. В книге «Проектирование на Java» Петера Коуда и Марка Мейфилда имеется целая глава «Проектирование с использованием композиции вместо наследования». Многие ранние объектно-ориентированные платформы даже не поддерживали истинное наследование. Когда Visual Basic превращался в Visual Basic .NET, первые объектно-ориентированные реализации не содержали возможностей по строгому наследованию. Платформы вроде модели COM от компании Microsoft базировались на наследовании интерфей- сов (оно подробно рассматривается в главе 8).
    В настоящее время использование наследования по-прежнему остается важной темой дебатов. Абстрактные классы, представляющие собой форму наследова- ния, не поддерживаются напрямую в некоторых языках программирования, например Objective-C. Интерфейсы используются, даже если они не обеспечи- вают всей функциональности, которую предоставляют абстрактные классы.
    Хорошая новость заключается в том, что дискуссии насчет того, применять на- следование либо композицию, полезны, ведь они направлены на выработку взвешенного компромиссного решения. Как и во всех философских дебатах, обе

    141
    Наследование. .
    стороны пылко приводят свои аргументы. К счастью, как это обычно бывает, эти горячие дискуссии привели к правильному пониманию того, как использо- вать соответствующие технологии.
    Позднее в этой главе вы увидите, почему многие программисты считают, что наследования следует избегать и нужно предпочитать композицию. Аргумен- тация довольно сложна и хитроумна. На самом деле как наследование, так и композиция являются действующими методиками проектирования классов, и у каждой из них есть соответствующее место в инструментарии разработчика, использующего объектно-ориентированные технологии. А вам как минимум необходимо понимать обе эти методики, чтобы сделать правильный выбор при проектировании, не говоря уже о сопровождении унаследованного кода.
    Да, наследование часто неправильно используют или злоупотребляют им, но это происходит из-за непонимания того, что оно собой представляет, а не по- тому, что использование наследования в качестве стратегии при проектирова- нии — фундаментальный изъян.
    1   ...   11   12   13   14   15   16   17   18   ...   25


    написать администратору сайта