Рабочая программа по дисциплине Цели и задачи освоения дисциплины Дисциплина Объектноориентированный анализ и программирование
Скачать 339.98 Kb.
|
Основные шаблоны предназначены для решения таких повседневных задач как переадресация работы специализированному классу, обеспечение слабой связности системы и тому подобное. Подавляющее большинство программистов неявно применяет те или иные основные шаблоны: «делегирование», шаблон функционального дизайна, «неизменяемый объект» и так далее. Порождающие шаблоны проектирования — это шаблоны проектирования, которые абстрагируют процесс создания экземпляра класса. Применение шаблонов этого типа позволяет получить гребуемос сложное поведение объекта не посредством создания новых объектов через наследование, а с помощью композиции ряда более простых объектов. При этом порождающие шаблоны инкапсулируют знания о простых классах, применяемых в системе. Системе известны лишь интерфейсы сложного класса, полученного в результате композиции, но не известен принцип стыковки простых классов. К порождающим шаблонам принято относить «абстрактную фабрику», «строителя», «фабричный метод», «ленивую инициализацию», «прототип», «объектный пул», шаблон «одиночка». Задача, решаемая структурными шаблонами проектирования, — создание различных структур, которые изменяют интерфейс или реализацию уже существующих объектов. Как правило, данные действия бывают необходимы для того, чтобы облегчить процесс разработки или оптимизировать программу. Наиболее известными структурными шаблонами проектирования являются «адаптер», «мост», «компоновщик», «фасад», «декоратор», «приспособленец» и «заместитель». Поведенческими шаблонами проектирования принято называть шаблоны, которые определяют алгоритмы и способы взаимодействия объектов между собой. Наиболее типичными примерами поведенческих шаблонов являются «цепочка ответственности», «команда», «интерпретатор», «итератор», «посредник», «хранитель», «наблюдатель», «стратегия», «шаблонный метод» и «посетитель». Основные шаблоны проектирования Шаблон делегирования Одним из наиболее примитивных шаблонов проектирования является «делегирование». Решаемая им задача заключается в передаче ответственности за выполнение работы другому объекту. Такое решение позволяет изменить поведение без создания нового класса через наследование. Косвенным преимуществом с точки зрения архитектуры системы является повышение степени абстракции. Среди недостатков можно отметить снижение производительности, вызванное необходимостью дополнительной передачи параметров. Примером использования «делегирования» является следующий код. public class Bubblesorter { public void sort(int_. args) { boolean flag true; while(flag) { flag = false; for(int 1=0; i < args.length - 1; i++) if(args.i. > args.i + 1]) { flag = true; int tmp = args.i.; args.i. = args.i + 1]; args[i +1] = tmp; public class Datastorage { private BubbleSorter bs new BubbleSorter(); private int .. data; public Datastorage(int[: data) { if(data != null) this.data = data.clone(); } public int [ ] getDataO { return data null? null : data.c_one(); public void sort() { if(data != null) bs.sort(data); } public static void main(String args) { int.. data = {2, 3, 5, 8, 1, 15}; Datastorage ds new Datastorage(data); ds.sort(); data = ds.getData(); if(data != null) { for(int i = 0; i < data.length; i++) System.out.print(data i. + " "); System.out.frush (); В представленном примере класс Datastorage предназначен для хранения массива целых чисел. Одной из функций, которую обеспечивает Datastorage является также сортировка хранимого массива. Класс BubbleSorter в контексте решаемой задачи является специализированным средством для сортировки набора элементов. В связи с этим экземпляр этого класса включен в состав Datastorage как скрытый член. При вызове метода sort() Datastorage перепоручает работу объекту класса BubbleSorter. Неизменяемый объек т Интересным по своей внутренней организации является «неизменяемый объект» — основной шаблон, предназначенный для создания объектов, которые не могут быть модифицированы после своего создания. Примером использования этого шаблона в Java является класс String. Для создания неизменяемых объектов необходимо придерживаться следующих правил. Все ноля класса имеют модификатор final. Класс объявляется как final. Ссылка this не должна быть передана во время конструирования. Для всех полей, содержащих ссылки на изменяемые объекты (например массивы), совокупности или изменяемые классы действуют следующие правила. Имеют модификатор private. Никогда не возвращаются и никаким другим образом не становятся доступными вызывающим операторам. Являются единственными ссылками на те объекты, на которые они ссылаются. Не изменяют после конструирования состояние объектов, на которые они ссылаются. Очевидными преимуществами использования шаблона являются простота взаимодействия с неизменяемыми объектами, автоматическая поддержка безопасности потоков, защита от характерных для изменяемых объектов ошибок, а также возможность использования подобных классов в качестве ключей для хэш-коллекций (неизменность состояния гарантирует неизменность значения хэш-функции). Рассмотрим пример неизменяемого класса. public final class People implements Cloneable { private final int age; private final String name; private People, parent; public People(int age, String name) { this(age, name, null, null); public People(int age, String name, People parent) { this(age, name, null, null); public People(int age, String name, People parentO, People parentl) { this.age = age; this.name = name; parent new People 2.; try { if(parentO != null) parent .0. = (People) parentO.c_one(); if(parentl 1= null) parent, 1] = (People) parentl.c-one(); catch (CloneNotSupportedException e) { e.printStackTrace() ; public void printinformation() { printName(); System.out .printin (" \nAge: " + age) ; for(int i = 0; i < parent._ength; i++) if(parent.! != null) { System.out.print("Parent " + (i + 1) + ": "); parent. i. .printName(); } System.out.flush(); } public void printName() { System.out.printin(name); System.out.flush(); public static void main(Stringi. args) { People pl new People(30, "Mike"); People p2 new People(28, "Mary"); People p3 new People(6, "Andrew", pl, p2); p3.printinformation() ; В представленном примере класс People является неизменяемым. Поля age и name имеют модификатор final. Класс реализует интерфейс Clonable, а это значит, что его экземпляры могут быть клонированы (в памяти ЭВМ будет создана полностью независимая копия объекта). Массив parent имеет модификатор private, передаваемые в конструктор объекты клонируются перед помещением в массив parent. Таким образом обеспечивается безопасность ссылок. Метод printlnformationO выводит на экран полную информацию сх> объекте, а метод printNameO — только значение поля name. Шаблон функционального дизайна Наиболее общим из всех является основной шаблон функционального дизайна, подразумевающий максимально низкую связь между модулями. Каждый модуль имеет только одну обязанность и исполняет ее с минимальным влиянием на другие части программы. Следование принципам функционального дизайна упрощает код модулей и позволяет безопасно повторно использовать код. Простота кода модулей позволяет добиться простоты архитектуры и упрощение процедуры внесения изменений в дальнейшем. К сожалению, далеко нс всегда возможно выполнить полное разбиение системы таким образом, чтобы каждый модуль отвечал только за одну функцию системы. Порождающие шаблоны проектирования Фабричный метод «Фабричный метод» — порождающий шаблон проектирования, предоставляющий подклассам интерфейс для создания экземпляров некоторого класса. Фабрика делегирует создание объектов наследникам родительского класса. Такой прием позволяет использовать в коде программы нс специфические классы, а манипулировать абстрактными объектами на более высоком уровне. Шаблон имеет смысл использовать в одном из трех случаев. Если классу заранее неизвестно, объекты каких подклассов ему нужно создавать. Если класс спроектирован так, чтобы объекты, которые он создает, специфицировались подклассами. Когда класс делегирует свои обязанности одному из нескольких вспомогательных подклассов, а уточнение информации о том, какой класс примет эти обязанности на себя, планируется в процессе выполнения. Применение данного подхода позволяет сделать код создания объекта более универсальным: нс привязывать его к конкретным классам, а оперировать интерфейсом. Вместе с тем наиболее существенным недостатком предложенного шаблона является необходимость в наследнике класса-создателя для каждого нового типа класса-продукта. Рассмотрим такой пример. public interface SorterGenerator { Sorter getSorter(); public interface Sorter { void sort(int_. args); public class AscendingBubbleSorterGenerator implements SorterGenerator public Sorter getSorter() { return new AscendingBubbleSorter() ; public class DescendingBubbleSorterGenerator implements SorterGenerator public Sorter getSorter() { return new DescendingBubbleSorter(); public class AscendingBubbleSorter implements Sorter { public void sort(int_. args) { boolean flag = true; while(flag) { flag = false; for(int i = 0; i < args._ength - 1; i++) if(args.i) > args.i + 1]) { flag = true; int tmp = args. i. ; args[ij = args[i + 1] ; args.i + 1] = tmp; } } } } public class DescendingBubbleSorter implements Sorter public void sort(int[J args) { boolean flag = true; while(flag) { flag false; for(int i = 0; i < args._ength - 1; i++) if(args[i] < argsfi +1]) { flag = true; int tmp = args . i.; args. i. = args. i + 1]; args.i + 1] = tmp; } } public class Client { private static void print(int.. args) { if(args != null) { for(int i = 0; i < args.length; i++) System.out.print(args_i. + " "); System.out.printIn (); System.out.flush(); } |