Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Использование классов при организации исключений. Иерархия исключений




Базовый класс стандартн исключ-й С++ наз exeption. Он объявляет констр-р и деструктор, но не имеет членов.Класс исключ-й дел-ся:*исключ-я класса logic_error coo,oa.n о действияхкот не и б выполнены. Условия, опред-мые во время выполн-я проги, делают дальнейшее выполнение каких-либо действий бессмысленным.

*исключ-я класса runtime_error сообщают о неправильных рез-тах действий. Такие искллюч-я возник в рез-те действий, начальные условия выполнения кот-х были верными, например, пер-ры ф-ии бskb правильными, но окончат рез-т получ-ся неверным.

Все стандартные исключ-я возник как ошибки выполнения проги. Однако исключ-ия logic_error явл рез-том попытки выполнить что-либо, что не имеет смысла уже до этой попытки, например, вызов ф-ии с неправильн параметрами выполнения. Категория runtime_error включает действия, ошибочность кот-х проявл в процессе или после выполн-я.

Специфич классы исключ-й общ вида(в скобках их базовый класс):

domain_error(logic_error)-наруш-е внутренних усл-й перед вып-ем действия

invalid_argument(logic_error)-попытка вызова ф-ии с неверным пар-ром

length_error(logic_error)-попытка создания объекта большего, чем максимальн размер типа size_t

out_of_range(logic_error)-попытка вызова ф-ии с пар-ром, не входящ в допустим знач-я

bad_cast(logic_error)-неправильное использ-е опер-ра dynamic_cast

bad_typeid(logic_error)исп-е неправильн знач-я

range_error (runtime_error)-неправильн рез-т выпол-я

overflow_error(runtime_error)-арифметич переполнение(рез-т слишком большой для указан типа д-х)

bad_alloc(runtime_error)ошибка при динамич распред-ии памяти

20. Паттерны и их классификация

При реализации проектов по разработке программных систем и моделированию бизнес-процессов встречаются ситуации, когда решение проблем в различных проектах имеют сходные структурные черты. Попытки выявить похожие схемы или структуры в рамках объектно-ориентированного анализа и проектирования привели к появлению понятия паттерна, которое из абстрактной категории превратилось в непременный атрибут современных CASE-средств

Паттерны ООАП различаются степенью детализации и уровнем абстракции. Предлагается следующая общая классификация паттернов по категориям их применения:

· Архитектурные паттерны

· Паттерны проектирования

· Паттерны анализа

· Паттерны тестирования

· Паттерны реализации

Архитектурные паттерны(Architectural patterns) - множество предварительно определенных подсистем со спецификацией их ответственности, правил и базовых принципов установления отношений между ними.

Архитектурные паттерны предназначены для спецификации фундаментальных схем структуризации программных систем. Наиболее известными паттернами этой категории являются паттерны GRASP (General Responsibility Assignment Software Pattern). Эти паттерны относятся к уровню системы и подсистем, но не к уровню классов. Как правило, формулируются в обобщенной форме, используют обычную терминологию и не зависят от области приложения. Паттерны этой категории систематизировал и описал К. Ларман.

Паттерны проектирования (Design patterns) - специальные схемы для уточнения структуры подсистем или компонентов программной системы и отношений между ними.

Паттерны проектирования описывают общую структуру взаимодействия элементов программной системы, которые реализуют исходную проблему проектирования в конкретном контексте. Наиболее известными паттернами этой категории являются паттерны GoF (Gang of Four), названные в честь Э. Гаммы, Р. Хелма, Р. Джонсона и Дж. Влиссидеса, которые систематизировали их и представили общее описание. Паттерны GoF включают в себя 23 паттерна. Эти паттерны не зависят от языка реализации, но их реализация зависит от области приложения.

Паттерны анализа (Analysis patterns) - специальные схемы для представления общей организации процесса моделирования.

Паттерны анализа относятся к одной или нескольким предметным областям и описываются в терминах предметной области. Наиболее известными паттернами этой группы являются паттерны бизнес-моделирования ARIS (Architecture of Integrated Information Systems), которые характеризуют абстрактный уровень представления бизнес-процессов. В дальнейшем паттерны анализа конкретизируются в типовых моделях с целью выполнения аналитических оценок или имитационного моделирования бизнес-процессов.

Паттерны тестирования (Test patterns) - специальные схемы для представления общей организации процесса тестирования программных систем.

К этой категории паттернов относятся такие паттерны, как тестирование черного ящика, белого ящика, отдельных классов, системы. Паттерны этой категории систематизировал и описал М. Гранд. Некоторые из них реализованы в инструментальных средствах, наиболее известными из которых является IBM Test Studio. В связи с этим паттерны тестирования иногда называют стратегиями или схемами тестирования.

Паттерны реализации (Implementation patterns) - совокупность компонентов и других элементов реализации, используемых в структуре модели при написании программного кода.

Эта категория паттернов делится на следующие подкатегории: паттерны организации программного кода, паттерны оптимизации программного кода, паттерны устойчивости кода, паттерны разработки графического интерфейса пользователя и др. Паттерны этой категории описаны в работах М. Гранда, К. Бека, Дж. Тидвелла и др. Некоторые из них реализованы в популярных интегрированных средах программирования в форме шаблонов создаваемых проектов. В этом случае выбор шаблона программного приложения позволяет получить некоторую заготовку программного кода.

Абстрактная фабрика.

Паттерн Абстрактная фабрика (также известен как Kit(инструментарий)) - предоставляет интерфейс для создания семейств, связанных между собой, или независимых объектов, конкретные классы которых неизвестны. Паттерн относится к порождающим, так как связан с процессом создания объектов.Рассмотрим UML диаграмму шаблона:

Рассмотрим диаграмму на примере проектирования программы “Мир животных”, в которой мы хотим “упорядочить” всех животных живущих в Европе и Африке:

AbstractFactory (фабрика Континентов) - объявляет интерфейс для операций, создающих абстрактные объекты-продукты;

ConcreteFactory (фабрика для Африки, фабрика для Европы) - конкретная фабрика. Реализует операции, создающие конкретные объекты-продукты;

AbstractProduct (Хищник, Травоядный) - абстрактный продукт. Объявляет интерфейс для типа объекта-продукта;

Product (Лев, Волк, Бизон, Медведь) - конкретный продукт. Определяет объект-продукт, создаваемый соответствующей конкретной фабрикой. Реализует интерфейс Abstract Product;

Client (Мир животных(приложение)) - клиент. Пользуется исключительно интерфейсами, которые объявлены в классах AbstractFactory и AbstractProduct.

Таким образом в проектируемой программе, создавая(инстанцируя) конкретную фабрику (к примеру для Европы), мы можем создавать семейство объектов с похожим поведением (Волк - хищник, живущий в Восточной Европе или Заяц - травоядный с ценным мехом). При этом созданием объектов-продуктов занимается непосредственно сама фабрика, поэтому нам нужен только ее один экземпляр. Зацитирую бандитов:

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

Вот некоторые проблемы которые помогает решать этот паттерн:

- Задание имени класса привязывает вас к конкретной реализации, а не к конкретному интерфейсу. Это может осложнить изменение объекта в будущем. Чтобы уйти от такой проблемы, создавайте объекты косвенно.
- Уход от аппаратной и программной зависимости
- Если клиент «знает», как объект представлен, хранится или реализован, то при изменении объекта может оказаться необходимым изменить и клиента. Сокрытие этой информации от клиентов поможет уберечься от каскада изменений.
- Уход от сильной связанности

Наблюдатель.

Реализация данного паттерна используется для наблюдения за состоянием объектов в системе. Если состояние объектов изменяется в процессе их жизненного цикла, то Наблюдатель оповещает другие части системы об этих событиях.

В данной статье я попытаюсь как можно проще и понятнее рассказать об этом паттерне и привести пример программного кода на Java, реализующего Observer.
В каких случаях используется Наблюдатель?

*Если один объект должен передавать сообщения другим объектам, но при этом он не может или не должен знать об их внутреннем устройстве;

*В случае если при изменении одного объекта необходимо изменять другие объекты;

*Для предотвращения сильных связей между объектами системы;

*Для наблюдения за состоянием определенных объектов системы;

Наблюдаемый (observable) объект (а точнее субъект или subject) должен предоставлять интерфейс для регистрации и дерегистрации наблюдателей (listeners).
Ну а сами наблюдатели должны как минимум обладать открытым методом через который и будет происходить оповещение об изменении состояния субъекта. Этот метод часто называют notify.

Так как наблюдателей может быть достаточно много, для упрощения работы с ними можно использовать коллекцию (collection of observers). Приблизительно такой код я использую в этом случае:

public interface Observer {

void objectCreated(Object obj);

void objectModified(Object obj);

}

class EmptyObserver implements Observer {

public void objectCreated(Object obj) { }

public void objectModified(Object obj) { }

}

class Observers<T extends Observer> extends ArrayList<T> {

public void notifyObjectCreated(Object obj) {

for (Iterator<T> iter = (Iterator<T>) iterator(); iter.hasNext();)

iter.next().objectCreated();

}

public void notifyObjectModified(Object obj) {

for (Iterator<T> iter = (Iterator<T>) iterator(); iter.hasNext();)

iter.next().objectCreated();

}

}

Класс EmptyObserver может быть полезен в случае если у Наблюдателя достаточно большое количество notify методов. Тогда используя анонимные классы можно с легкостью создавать необходимые нам “узкоспециализированные” наблюдатели (те, у которых реализовано ограниченное количество методов) на лету:

Observers observers = new Observers();

observers.add(new EmptyObserver() {

public void objectCreated(Object obj) { /* реализация */ }

});

Далее, экземпляр класса Observers помещается в субъект за которым должно вестись наблюдение. Во всех местах кода, где происходит интересующее нас действие с классом-субъектом, добавляем соответствующий вызов notify метода у коллекции наблюдателей:

public class Subject {

Observers observers = new Observers();

private Object field;

public void setField(Object o) {

field = o;

observers.notifyObjectModified(this);

}

}

Нюансы предлагаю обсуждать в комментариях.

Классический пример использования паттерна Observer - это классы из пакета Java Swing. В Swing паттерн Наблюдатель используется для организации слабой взаимозависимости между моделью и графическими объектами. Методы notify вызываются при изменении значений свойств модели и передают информацию в виджеты.
Кстати, очень рекомендую всем посмотреть исходный код Java Swing. Это действительно очень качественно спроектированная библиотека.

23. Классификация типов данных.

В языке программирования C# типы данных подразделяются на три категории:

· Значение

· Ссылка

· Указатель

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

int x = 5;

объявляет переменную - целую со знаком, размером 32 бита, с именем x и начальным значением, равным 5. Ниже приведена соответствующая этому объявлению диаграмма:

Обратите внимание на то, как число 5 размещено на диаграмме.

Переменные-ссылки содержат адреса объектов, размещенных в динамической памяти. Следующий код объявляет переменную с именем y, типа object и инициализирует ее с помощью оператора new. Таким образом она получает адрес экземпляра object, размещенного в динамической памяти (object -- это базовый класс для всех типов в C#, но об этом чуть ниже).

object y = new object();

И наконец -- переменные-указатели. Они похожи на указатели в языках программирования C и C++. Очень важно понимать, что и переменные-ссылки и переменные-указатели, фактически, представляют собой адрес в памяти, но на этом их сходство заканчивается. Переменные-ссылки отслеживаются сборщиком "мусора", указатели -- нет. Переменные-указатели допускают выполнение арифметических операций над ними, ссылки -- нет. Бесконтрольное использование указателей в программе в принципе небезопасно, поэтому в языке C# допускается работать с только внутуказателямири unsafe (небезопасных) блоков (небезопасный код должен помечаться зарезервированным словом unsafe, например:

static unsafe void FastCopy (byte[] src, byte[] dst, int count)

{

// здесь допустимо использовать указатели

}

int[] mas1 = new int[5];

int[] mas1 = {5, 3, 5, 7, 15};

int[,] mas1 = new int[3, 5];

int[][] mas1 = new int[5][];

for (int x = 0; x < 5; x++)

{

mas1[x] = new int[x+1];

}

for (int x = 0; x < 5; x++)

for (int y = 0; y < x+1; y++)

mas1[x][y] = x + y;

for (int x=0; x < 5; x++)

{

for (int y=0; y < x+1; y++)

{

Console.Write(mas1[x][y]+"\\t");

}

Console.WriteLine();

}

Console.Read();

Хотелось бы напоследок еще раз обратить ваше внимание на то, что массив в C# - это объект, поэтому с ним можно выполнять те же действия, что и с другими объектами. У массивов есть множество полезных методов, которые нужно знать и уметь ими пользоваться. Перечислю лишь наиболее употребляемые:
Sort() - сортировка одномерного массива. Пример:

int[] mas2 = { 3, 4, 1 };

Array.Sort(mas2);

Clear() - очищает массив. Всем элементам присваивается значение по умолчанию. Пример:

int[] mas2 = { 3, 4, 1 };

Array.Сlear(mas2);

СopyTo() - копирование массива. В примере ниже мы создаем 2 массива. Длина первого 3, второго - 4. Первый массив мы заполняем при создании. Второй массив заполняется значениями по умолчанию, т.е. нулями. После чего мы копируем первый массив во второй, начиная с индекса 1, т.е. со второй ячейки:

int[] oldmass = { 3, 4, 1 };

int[] newmass = new int[4];

oldmass.CopyTo(newmass, 1);

Length - свойство массива содержащего его длину. Пример:

int[] mas = { 3, 4, 1 };

Console.WriteLine(mas.Length);

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

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...