Идиомы и стили С++ - страница 25

Шрифт
Интервал

стр.

Все остальное - дело техники. Сразу поясняю код: класс CLockable (базовый) содержит указатель на транзакцию, к которой принадлежит в данный момент, а так же чистые виртуальные функции rollback и commit, назначение которых очевидно. Класс CTransaction представляет собой транзакцию, и содержит в себе список задействованных объектов - затем чтобы роллбачить или коммитить их все вместе, да чтоб на ходу можно проверить - принадлежит ли объект некоей транзакции или нет. Функция addLock() добавляет объект к транзакции, то есть распространяет свое действие на него, тем самым блокируя изменения со стороны других клиентов. После использования объекты автоматически разрегистрируются.

Хочу еще раз напомнить о принципе, который в этом Шаге формулируется первый раз: если существует определенная, законченная логика взаимодействия объектов или систем - она выносится на отдельный уровень. Поддержка транзакций очевидно является законченной бизнес-логикой, и, следовательно, должна быть вынесена на специальный уровень. Пусть классы реализуют свою функциональность, не заботясь о свопе, многозадачности-поточности, транзакциях, доступе, приоритетах, авторизациях, синхронизации, сборке мусора (garbage collection) или уплотнении памяти - это не его проблемы. Это - другие уровни, которыми занимаются другие классы, или даже системы. В современном компьютерном мире этот принцип сегодня доминирует, именно на него работают новомодные COM+ с MTS, IBM-websphera, JavaBeans, и множество иных. То, что грамотная корпоративная система должна работать в минимум четырех уровнях, уже является прописной истиной: данные, бизнес-логика сервера, бизнес-логика клиента, клиент.

Понимаете теперь, в чем преимущество смарт-указателей? Они позволяют с легкостью создавать новые уровни бизнес-логик без привлечения дополнительных средств и схем, а едиными только средствами языка. Попробуйте сделать что-либо подобное на языке, который не поддерживает указателей и перегрузки операторов (да шаблоны еще)! Вот код.

>#include "ampstack.h"

>// Абстрактный базовый класс

>class CLockable {

> friend class CTransaction;

>protected:

> // текущая транзакция, если есть

> CTransaction* m_trans;

>public:

> CLockable (): m_trans (NULL) {}

> // регистрируемся в какой-то транзакции

> int regObj (CTransaction* _pt);

> // и разрегистрируемся

> void unregObj();

> virtual ~CLockable() {}

> virtual void rollback () =0;

> virtual void commit() =0;

>};


>// Класс транзакции

>class CTransaction {

> friend class CLockable;

>private:

> // коллекция зарегистрированных объектов

> ampstack‹CLockable› m_locks;

> // добавить объект к транзакции

> void addLock (CLockable*);

>public:

> virtual ~CTransaction ();

>// закрепить или отменить все изменения во всех

>// зарегистрированных объектах.

> void commit();

> void rollback();

>// проверить, зарегистрирован ли объект в этой транзакции

> int allready_locked(CLockable*);

>};


>// зарегистрироваться в транзакции

>inline int CLockable::regObj (CTransaction* _pt) {

> if (m_trans!= NULL) return 0;

> else {

>  _pt-›addLock(this);

>  m_trans = _pt;

>  return 1;

> }

>}


>// разрегистрироваться

>inline void CLockable::unregObj() {

> m_trans = NULL;

>}


>// добавление объекта к транзакции.

>inline void CTransaction::addLock(CLockable* _lc) {

> // а именно, воткнуть указатель на него в стек.

> m_locks.push (_lc);

>}


>// закрепление всех объектов

>void CTransaction::commit() {

> // создаем итератор

> ampIter‹CLockable› it(&(this-›m_locks));

> // пробежались по всем, закрепились.

> it.goStart();

> while (!it.isLast()) it.moveNext()-›commit();

> // Всех выкинуть из стека, разрегистрировать.

> while (!m_locks.isEmpty()) m_locks.pop()-›unregObj();

>}


>// отмена всех объектов

>void CTransaction::rollback() {

> // создали итератор

> ampIter‹CLockable› it(&(this-›m_locks));

> // пробежались по всем, отменились.

> it.goStart();

> while (!it.isLast()) it.moveNext()-›rollback();

> // Всех выкинуть из коллекции и разрегистрировать

> while (!m_locks.isEmpty()) m_locks.pop()-›unregObj();

>}


>// проверка, зарегистрирован ли объект.

>int CTransaction::allready_locked(CLockable* _lc) {

> // создали итератор

> ampIter‹CLockable› it(&(this-›m_locks));


стр.

Похожие книги