Рабочая программа по дисциплине Цели и задачи освоения дисциплины Дисциплина Объектноориентированный анализ и программирование
![]()
|
static boolean isNondecreasing(int[] arg, int length) { for(int i = 0; i < length - 1; i++) if(arg.i_ > arg.i + 11) return false; return true; static boolean isNonincreasing(int[I arg, int length) { for(int 1=0; i < length - 1; i++) if(arg.i. < arg.i + 1]) return false; return true; } public class Adapter { public static boolean isMonotnic(int.. arg) { return SequencesProcessor.isNondecreasing(arg, arg.length) SequencesProcessor.isNonincreasing(arg, arg._ength); public class Client { public static void main(String[] args) { inti] a = {1, 2, 5, 7, 15, 23); inti] b = {5, 13, 51, 41, 45, 645}; int[] c = {78, 18, -10, -10}; if(Adapter.isMonotnic(a)) System.out.printin("Sequence A is monotonic"); if(Adapter.isMonotnic(b)) System.out.printin("Sequence В is monotonic"); if(Adapter.isMonotnic(c)) System.out.printin("Sequence C is monotonic"); System.out.f_ush (); Класс-библиотека SequencesProcessor декларирует и реализует методы для обработки последовательностей, в частности — для проверки на невозростание и неубывание (isNonincreasinf и isNondecreasing). Параметрами методов являются проверяемый массив целых чисел и его размер. Очевидно, что передача размера не является необходимой операцией. Именно поэтому клиентский класс Client для проверки монотонности массива взаимодействует с библиотекой через адаптер Adapter, который позволяет модифицировать сигнатуру вызываемого метода. Фасад «Фасад» — структурный шаблон проектирования, предоставляющий общий простой интерфейс для доступа к ряду модулей подсистемы. Зачастую сложные программные комплексы состоят из большого числа компонентов. При этом некоторым разработчикам необходим доступ к отдельным подсистемам. «Фасад» предлагает типовой сценарий взаимодействия, устраивающий большинство разработчиков, но при этом не скрывает доступ к отдельным компонентам системы. В сравнении с подходом модульной декомпозиции системы, данный шаблон обладает рядом важных преимуществ. Во-первых, в большинстве случаев клиенты изолированы от подсистем, что приводит к уменьшению числа объектов, с которыми приходится работать, и упрощает взаимодействие со всей системой в целом. Во-вторых, использование «фасада» в целом облегчает устройство всей системы. Шаблон позволяет ослабить зависимости между подсистемами и разложить всю систему на слабосвязанные слои. В-третьих, «фасад» не препятствует клиентам работать непосредственно с отдельными компонентами. Таким образом, клиент имеет выбор — работать ли непосредственно с подсистемами или с «фасадом». Рассмотрим пример использования «фасада». import java.io.*; import java.util.*; public class DataFileReader { public Integer[j dataReading(String filename) throws lOException { Scanner in new Scanner(new FileReader(new File(filename))); Vector for(int i = 0; i < n; i++) data.add(new Integer(in.nextlnt())); in.close (); Integer. ex new Integerflj; return data.toArray(ex); public class Bubblesorter { public void sort(Integerij args) { boolean flag = true; while(flag) { flag = false; for(int i = 0; i < args.length - 1; i++) if(args.i. > args.i + 1] ) { flag = true; int tmp = args.i]; args[i] = args[i + 1]; argsii + 1] = tmp; public class DataFileWriter { lOException { Printwriter out new Printwriter(filename) ; out.printin(data._ength) ; for(int i = 0; i < data.length; i++) out.printin(data[i ]); out.close(); public class Client { private DataFileReader dfr new DataFileReader(); private BubbleSorter bs new BubbleSorter(); private DataFileWriter dfw new DataFileWriter(); public void datalnFilesSorter(String. .. filenames) { for(int i = 0; i < filenames.length; i++) { try { Integer.. data = dfr.dataReading(filenames.i. [ 0 ] ); bs.sort(data); dfw.dataWriter(filenames[ij [1], data); catch (Exception e) { e.printStackfrace() ; } public static void main(String[] args) { Client cl new Client (); String filenames = {{"l.in", "l.out"), {"2.in", "2.out"}, {"3.in", "3.out"}}; cl.datalnFilesSorter(filenames) ; В представленном примере классы DataFileReader, BubbleSorter и DataFileWriter как раз и представляют собой модули системы. Каждый из них обеспечивает соответствующий функционал: считывание данных с жесткого диска компьютера, сортировка данных, запись результата на жесткий диск. Класс Client, являющийся «фасадом», декларирует метод datalnFilesSorter(). Этот метод содержит описание наиболее частого сценария действий в контексте рассматриваемой системы: считывание массива целых чисел из заданного файла, сортировка и запись результата в заданный файл. Кроме того, метод ориентирован на групповую операцию, то есть сценарий применяется последовательно к нескольким файлам. ![]() ![]() Диаграмма шаблона «декоратор» Декоратор Важным структурным шаблоном проектирования является «декоратор», который позволяет добавлять объекту новые обязанности. Применение «декоратора» целесообразно в тех случаях, когда требуется динамическое добавление обязанностей объектам, или когда требуется реализация обязанностей, которые в дальнейшем могут быть сняты с объекта. Очевидными достоинствами описанного шаблона является, во-первых, большая гибкость, чем при статическом наследовании, а во-вторых, упрощение структуры отдельных классов. При этом использование шаблона часто приводит к «раздроблению системы» (значительному возрастанию количества мелких объектов). В некотором роде данный шаблон — альтернатива порождению подклассов. Лучше всего принцип работы «декоратора» можно понять из диаграммы классов. Здесь Interface — это интерфейс, который декларирует метод для совершения базовой операции. Component — реализующий интерфейс Interface класс, на который возлагаются дополнительные обязанности. Decorator — абстрактный класс, который хранит ссылку на объект Component и реализует operation)) через делегирование. ConcreteDecorator — класс-наследник от Decorator, который добавляет функциональности объекту Component. Мост Необходимым элементом более общего шаблона функционального дизайна является структурный шаблон «мост», позволяющий отделить абстракцию от реализации таким образом, чтобы и то, и другое можно было изменять независимо. «Мост» эффективен, прежде всего, в тех случаях, когда необходимо избегать постоянной привязки абстракции к реализации (например, реализация должна быть выбрана во время выполнения). Существенным преимуществом является то, что чаще всего изменение в коде реализации не приводит к необходимости перекомпиляции кода клиента. Таким образом, иерархии классов, описывающих абстракцию, и классов, отвечающих за поведение, могут изменяться независимо. Также в качестве достоинства шаблона стоит отметить высокую степень инкапсуляции. Диаграмма классов для шаблона «мост» представлен на рисунке. ![]() ![]() Диаграмма шаблона «мост» Здесь абстрактный класс Abstraction определяет метод operation)), используемый клиентами. Класс ConcreteAbstraction наследует от класса Abstraction и непосредственно используется клиентами. Интерфейс Implementation предоставляет метод, реализующий операцию класса Abstraction. ConcretelmplementationA и ConcretelmplementationB реализуют интерфейс Implementation. Заместитель Последним в этом разделе будет разобрано еще одно интересное архитектурное решение. Рассмотрим следующую ситуацию. Пусть в программе используется несколько «тяжелых» изображений, и их инициализация (загрузка графического представления их указанного файла) требует значительного времени и системных ресурсов. Однако, эти изображения расположены не на главной форме и вообще отображаются не одновременно. В таком случае хорошим решением является инициализация таких объектов по требованию. Пусть в контексте рассматриваемого примера для корректной загрузки прочих компонентов требуется знать размеры всех изображений (это может быть необходимо в случае сложной верстки). Именно для таких ситуаций и предназначен шаблон «заместитель», который позволяет выполнять инициализацию объектов по требованию, и кроме этого, обладает каким-либо непосредственно связанным с замещаемым объектом дополнительным функционалом (в данном случае — возможностью сообщить реальные размеры изображения без его загрузки). Другими словами, возможна ситуация, когда нецелесообразно выполнять инициализацию всех объектов в начале работы приложения, однако отложенная загрузка не является приемлемым решением. «Заместитель» применяется в тех случаях, когда необходимо использовать не просто указатель на объект, но и дополнительный функционал, связанный с этим указателем. Структура шаблона приведена на диаграмме классов. ![]() ![]() Диаграмма шаблона «заместитель» На диаграмме классы и интерфейсы выполняют следующие роли. Subject — интерфейс, предоставляющий клиентам метод доступа к объектам. ConcreteSubject — конкретный субъект, реализующий интерфейс Subject. Proxy — «заместитель» ConcreteSubject, хранящий на него ссылку и реализующий интерфейс Subject. Помимо основного метода rcqucstO, который переадресует запрос ConcreteSubject, обладает дополнительной функциональностью, реализованной в метода otherFunctional(). Основным преимуществом шаблона является появление нового уровня функциональности при доступе к объекту, при этом ряд операций приобретает отложенный характер, что в некоторых случаях может значительно повысить общую производительность системы. Однако нс надо забывать, что использование «заместителя» чревато увеличением времени отклика при обращении к объекту. Поведенческие шаблоны проектирования Цепочка ответс твенност и Первым рассматриваемым в этом разделе архитектурным решением будет «цепочка ответственности» — поведенческий шаблон проектирования, предназначенный для связи объектов-обработчиков запросов в цепочку и передачи запроса по ней до тех пор, пока он не будет обработан. Шаблон предназначен для тех ситуаций, когда конкретный обработчик запроса клиента заранее неизвестен и должен быть найден автоматически. Помимо этого «цепочка ответственности» может оказаться удобной в ситуации, когда набор объектов, способных обрабатывать запросы, должен динамически меняться. Примером «цепочки ответственности» может являться следующая структура, предназначенная для хранения нар целых чисел ключ-значение. import java.util.HashMap; public interface Finder { public int getData(int key); public void add(int key, int data); } public class SlowFinder implements Finder { private HashMap SlowFinder() { data new HashMap public int getData(int key) { return data.get(key); } public void add(int key, int data) { this.data.put(key, data); } public class FastFinder implements Finder { |