Разделы презентаций


паттерны проектирования 2.pptx

Содержание

Prototype (Прототип)

Слайды и текст этой презентации

Слайд 1Паттерны проектирования (Design patterns)

Паттерны проектирования (Design patterns)

Слайд 2Prototype (Прототип)

Prototype (Прототип)

Слайд 3Назначение паттерна «Прототип»
Задает виды создаваемых объектов с помощью экземпляра-прототипа и

создает новые объекты путем копирования этого прототипа
Подобно «Абстрактной фабрике» и

«Строителю» паттерн «Прототип» скрывает от клиента конкретные классы продуктов, уменьшая число известных клиенту имен
Назначение паттерна «Прототип»Задает виды создаваемых объектов с помощью экземпляра-прототипа и создает новые объекты путем копирования этого прототипаПодобно

Слайд 4Структура
Client
Operation()
Prototype
Clone()

Вернуть копию самого себя
Вернуть копию самого себя


Объявляет интерфейс для клонирования

самого себя
Реализует операцию клонирования себя
Создает новый объект, обращаясь к прототипу

с запросом клонировать себя
СтруктураClientOperation()PrototypeClone()Вернуть копию самого себяВернуть копию самого себяОбъявляет интерфейс для клонирования самого себяРеализует операцию клонирования себяСоздает новый объект,

Слайд 5Отношения между участниками паттерна
Клиент обращается к прототипу, чтобы тот создал

свою копию

Отношения между участниками паттернаКлиент обращается к прототипу, чтобы тот создал свою копию

Слайд 6Применимость паттерна «Прототип»
Система не должна зависеть от того, как в

ней создаются, компонуются и представляются продукты
Инстанцируемые классы определяются во время

выполнения
Например, с помощью динамической загрузки
Избежание построения иерархий классов или фабрик, параллельных иерархии классов продуктов
Экземпляры класса могут находиться в одном из не очень большого числа различных состояний
Может оказаться удобнее задать соответствующее число прототипов и клонировать их
Применимость паттерна «Прототип»Система не должна зависеть от того, как в ней создаются, компонуются и представляются продуктыИнстанцируемые классы

Слайд 7Преимущества использования паттерна «Прототип»
Добавление и удаление продуктов во время выполнения
Клиенту

просто сообщается о новом экземпляре-прототипе
Спецификация новых объектов путем изменения значений
Склонированный

и слегка модифицированный экземпляр прототипа может быть также зарегистрирован в роли прототипа
Преимущества использования паттерна «Прототип»Добавление и удаление продуктов во время выполненияКлиенту просто сообщается о новом экземпляре-прототипеСпецификация новых объектов

Слайд 8Преимущества использования паттерна «Прототип»
Специфицирование новых объектов путем изменения структуры
Уменьшение числа

подклассов
Фабричный метод часто порождает иерархию классов «Создатель», параллельную иерархии классов

продуктов
Паттерн «прототип» может клонировать прототип, а не запрашивать фабричный метод
Динамическое конфигурирование приложения
Динамически загружаемые классы прототипов регистрируют свои экземпляры в «диспетчере прототипов»
Преимущества использования паттерна «Прототип»Специфицирование новых объектов путем изменения структурыУменьшение числа подклассовФабричный метод часто порождает иерархию классов «Создатель»,

Слайд 9Пример использования паттерна «Прототип»
Палитра готовых фигур в программах вроде Microsoft

PowerPoint
Пользователь может создавать фигуры на основе имеющихся прототипов фигур
Количество прототипов

фигур потенциально может быть неограниченным
Пример использования паттерна «Прототип»Палитра готовых фигур в программах вроде Microsoft PowerPointПользователь может создавать фигуры на основе имеющихся

Слайд 10Иерархия
Абстрактный прототип
Конкретные прототипы

ИерархияАбстрактный прототипКонкретные прототипы

Слайд 11Исходный код прототипов
class CShape
{
protected:
CShape(float l, float t, float w, float

h)
{/*...*/}
public:
virtual ~CShape(){}
virtual CShape* Clone()const = 0;
float GetWidth()const{/*...*/}
float GetHeight()const{/*...*/}
float GetLeft()const{/*...*/}
float GetTop()const{/*...*/}
};
typedef

boost::shared_ptr CShapePtr;

class CEllipse : public CShape
{
public:
CEllipse(float l, float t, float w, float h)
:CShape (l, t, w, h){/*...*/}
virtual CShape* Clone()const
{return new CEllipse(*this);}
};

class CRectangle : public CShape
{
public:
CRectangle(float l, float t, float w, float h)
:CShape (l, t, w, h){/*...*/}
virtual CShape* Clone()const
{
return new CRectangle(*this);
}
};
class CCallout : public CShape
{
public:
CCallout(float l, float t, float w, float h, float adjX, float adjY) :CShape (l, t, w, h){}
virtual CShape* Clone()const
{
return new CCallout(*this);
}
float GetAdjustmentPointX(){/*...*/}
float GetAdjustmentPointY(){/*...*/}
};

Исходный код прототиповclass CShape{protected:	CShape(float l, float t, float w, float h)	{/*...*/}public:	virtual ~CShape(){}	virtual CShape* Clone()const = 0;	float GetWidth()const{/*...*/}	float

Слайд 12Диспетчер прототипов фигур
class CShapeManager
{
public:
void RegisterShapePrototype(std::string const& id, CShapePtr pShape)
{
m_prototypes[id] =

pShape;
}

CShapePtr CreateShape(std::string const& id)const
{
PrototypeMap::const_iterator it = m_prototypes.find(id);
if (it == m_prototypes.end())
{
throw

std::invalid_argument(“Unknown shape type");
}
// создание фигуры на основе найденного прототипа
return CShapePtr(it->second->Clone());
}
private:
typedef std::map PrototypeMap;
PrototypeMap m_prototypes;
};

Слайд 13Использование прототипов
int main(int argc, char * argv[])
{
CShapeManager shapes;
// регистрируем прототипы

фигур в менеджере прототипов при старте приложения
shapes.RegisterShapePrototype("Ellipse", CShapePtr(new CEllipse(0, 0,

10, 10)));
shapes.RegisterShapePrototype("Rectangle", CShapePtr(new CRectangle(0, 0, 10, 10)));
shapes.RegisterShapePrototype("Callout", CShapePtr(new CCallout(0, 0, 10, 10, 5, 15)));

// ...

// создаем выноску при помощи диспетчера прототипов
std::string shapeType = “Callout”;
CShapePtr pShape = shapes.CreateShape(shapeType);
// ...

return 0;
}
Использование прототиповint main(int argc, char * argv[]){	CShapeManager shapes;	// регистрируем прототипы фигур в менеджере прототипов при старте приложения	shapes.RegisterShapePrototype(

Слайд 14Недостатки паттерна прототип
Каждый подкласс класса Prototype должен реализовывать операцию Clone
Для

уже существующих классов реализация операции клонирования может быть проблематичной
В ряде

случаев задача «глубокого» клонирования может быть нетривиальной
Во внутреннем представлении объекта содержатся другие объекты
Внутри объекта присутствуют круговые ссылки.
Недостатки паттерна прототипКаждый подкласс класса Prototype должен реализовывать операцию CloneДля уже существующих классов реализация операции клонирования может

Слайд 15Singleton (Одиночка)

Singleton (Одиночка)

Слайд 16Назначение паттерна «Одиночка»
Гарантирует, что у класса есть только один экземпляр,

и предоставляет к нему глобальную точку доступа
Приложению может потребоваться одна-единственная

фабрика компонентов пользовательского интерфейса
Приложению может потребоваться одна-единственная база данных
Назначение паттерна «Одиночка»Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступаПриложению

Слайд 17Применимость
Должен быть ровно один экземпляр некоторого класса, легко доступный всем

клиентам
Единственный экземпляр должен расширяться путем порождения подклассов, и клиентам нужно

иметь возможность работать с расширенным экземпляром без модификации своего кода
ПрименимостьДолжен быть ровно один экземпляр некоторого класса, легко доступный всем клиентамЕдинственный экземпляр должен расширяться путем порождения подклассов,

Слайд 18Структура
Singleton
static Instance()
SingletonOperation()
GetSingletonData()
Определяет операцию Instance() (статический метод в C++), которая позволяет

клиентам получать доступ к единственному экземпляру
Может нести ответственность за создание

собственного уникального экземпляра

static uniqueInstance
singletonData


return uniqueInstance

СтруктураSingletonstatic Instance()SingletonOperation()GetSingletonData()Определяет операцию Instance() (статический метод в C++), которая позволяет клиентам получать доступ к единственному экземпляруМожет нести

Слайд 19Отношения
Клиенты получают доступ к экземпляру класса Singleton только через его

операцию Instance


ОтношенияКлиенты получают доступ к экземпляру класса Singleton только через его операцию Instance

Слайд 20Достоинства
Контролируемый доступ к единственному экземпляру
Уменьшение числа имен по сравнению с

глобальными переменными
Допускает уточнение операций и представления
От класса Singleton можно порождать

подклассы
Допускает переменное число экземпляров
Необходимо лишь изменить операцию Instance
Большая гибкость, чем у статических функций класса
В C++ статические функции не могут быть виртуальными => нельзя использовать полиморфизм
ДостоинстваКонтролируемый доступ к единственному экземпляруУменьшение числа имен по сравнению с глобальными переменнымиДопускает уточнение операций и представленияОт класса

Слайд 21Простейшая реализация
template class CSingleton : public boost::non_copyable
{
public:
static T& Instance()
{
//

у класса T есть конструктор по умолчанию
static T theSingleInstance;
return

theSingleInstance;
}
};

class COnlyOne : public CSingleton
{
friend class CSingleton
COnlyOne(){} // закрытый конструктор по умолчанию
//.. интерфейс класса
};

int main()
{
COnlyOne & one = COnlyOne::Instance();
// использование экземпляра one
}
Простейшая реализацияtemplate class CSingleton : public boost::non_copyable{public:	static T& Instance()	{		// у класса T есть конструктор по умолчанию		static T

Слайд 22Thread-safe реализация паттерна «Одиночка»
#include
#include
#include

// Warning: If T's

constructor throws, instance() will return a null reference.
template class

CSingleton : private boost::noncopyable
{
public:
static T& instance()
{
boost::call_once(init, flag);
return *t;
}
static void init() // never throws
{
t.reset(new T());
}
protected:
~CSingleton() {}
CSingleton() {}
private:
static boost::scoped_ptr t;
static boost::once_flag flag;
};
template boost::scoped_ptr CSingleton::t(0);
template boost::once_flag CSingleton::flag = BOOST_ONCE_INIT;
Thread-safe реализация паттерна «Одиночка»#include #include #include // Warning: If T's constructor throws, instance() will return a null

Слайд 23Пример использования
#include
#include
#include
// Warning: If T's constructor throws,

instance() will return a null reference.
template class Singleton :

private boost::noncopyable
{
public:
static T& Instance()
{
boost::call_once(Init, flag);
return *t;
}
static void Init() // never throws
{
t.reset(new T());
}
protected:
~Singleton() {}
Singleton() {}
private:
static boost::scoped_ptr t;
static boost::once_flag flag;
};
template boost::scoped_ptr Singleton::t(0);
template boost::once_flag Singleton::flag = BOOST_ONCE_INIT;

class CMyClass : public CSingleton
{
friend class CSingleton;
public:
void DoSomething()
{
std::cout << "Something";
}
private:
CMyClass();
};
void test()
{
CMyClass::Instance().DoSomething();
}

Пример использования#include #include #include // Warning: If T's constructor throws, instance() will return a null reference.template class

Слайд 24Особенности реализации паттерна «Одиночка» в C++
В C++ не определяется порядок

вызова конструкторов для глобальный объектов через границы единиц трансляции
Между одиночками

не может существовать никаких зависимостей
Особенности реализации паттерна «Одиночка» в C++В C++ не определяется порядок вызова конструкторов для глобальный объектов через границы

Слайд 25Обсуждение порождающих паттернов

Обсуждение порождающих паттернов

Слайд 26Способы параметризации системы классами создаваемых объектов
Порождение подклассов, от класса, создающего

объекты
Фабричный метод
Композиция объектов
Параметром системы является класс (фабричный объект), которому известно

о классах объектов-продуктов
Абстрактная фабрика
Строитель
Прототип
Способы параметризации системы классами создаваемых объектовПорождение подклассов, от класса, создающего объектыФабричный методКомпозиция объектовПараметром системы является класс (фабричный

Слайд 27Паттерн «Прототип»
Лучше всего подходит для каркасов визуальных графических редакторов
Сокращает число

подклассов, создающих объекты
Метод Clone() можно использовать также для создания дубликатов

объектов
Паттерн «Прототип»Лучше всего подходит для каркасов визуальных графических редакторовСокращает число подклассов, создающих объектыМетод Clone() можно использовать также

Слайд 28Паттерн «Фабричный метод»
В классе-наследнике требуется лишь переопределить операцию инстанцирования продукта
Не

следует использовать, если инстанцируемый класс никогда не изменяется или инстанцирование

выполняется внутри операции, которую можно заместить в подклассах
Паттерн «Фабричный метод»В классе-наследнике требуется лишь переопределить операцию инстанцирования продуктаНе следует использовать, если инстанцируемый класс никогда не

Слайд 29Абстрактная фабрика, прототип, строитель
Плюсы:
Проекты, использующие данные паттерны, являются более гибкими
Минусы:
Повышенная

сложность

Абстрактная фабрика, прототип, строительПлюсы:Проекты, использующие данные паттерны, являются более гибкимиМинусы:Повышенная сложность

Слайд 30Структурные паттерны

Структурные паттерны

Слайд 31Структурные паттерны
Определяют различные сложные структуры, изменяющие интерфейс существующих объектов или

его реализацию
Адаптер (Adapter)
Мост (Bridge)
Компоновщик (Composite)
Декоратор (Decorator)
Фасад (Facade)
Приспособленец (Flyweight)
Заместитель (Proxy)

Структурные паттерныОпределяют различные сложные структуры, изменяющие интерфейс существующих объектов или его реализациюАдаптер (Adapter)Мост (Bridge)Компоновщик (Composite)Декоратор (Decorator)Фасад (Facade)Приспособленец

Слайд 32Адаптер (Adapter)

Адаптер (Adapter)

Слайд 33Паттерн Adapter
Преобразует интерфейс одного класса в интерфейс другого, который ожидают

клиенты
Обеспечивает совместную работу классов с несовместимыми интерфейсами, которая без него

была бы невозможна
Альтернативное название – Wrapper (Обертка)
Типы:
Адаптер класса
Адаптер объекта
Паттерн AdapterПреобразует интерфейс одного класса в интерфейс другого, который ожидают клиентыОбеспечивает совместную работу классов с несовместимыми интерфейсами,

Слайд 34Применимость
Необходимо использовать существующий класс, но его интерфейс не соответствует заданным

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

или не связанными с ним классами, имеющими несовместимые интерфейсы
Использование нескольких существующих подклассов, приспосабливая интерфейс их общего родительского класса (только для адаптера объектов)
ПрименимостьНеобходимо использовать существующий класс, но его интерфейс не соответствует заданным требованиямСоздание повторно используемого класса, который должен взаимодействовать

Слайд 35Структура адаптера класса
Client
Target
Request()

SpecificRequest()

Adaptee
SpecificRequest()

(реализация)
Определяет зависящий от предметной области интерфейс, которым пользуется

Client
Взаимодействует с объектами, удовлетворяющими интерфейсу Target
Определяет существующий интерфейс, который нуждается

в адаптации

Адаптирует интерфейс Adaptee к интерфейсу Target

Структура адаптера классаClientTargetRequest()SpecificRequest()AdapteeSpecificRequest()(реализация)Определяет зависящий от предметной области интерфейс, которым пользуется ClientВзаимодействует с объектами, удовлетворяющими интерфейсу TargetОпределяет существующий

Слайд 36Структура адаптера объектов
Client
Target
Request()

adaptee->SpecificRequest()

Adaptee
SpecificRequest()
adaptee

Структура адаптера объектовClientTargetRequest()adaptee->SpecificRequest()AdapteeSpecificRequest()adaptee

Слайд 37Отношения (адаптер класса)
Адаптер класса адаптирует Adaptee к Target, перепоручая действия

конкретному классу Adaptee
Этот паттерн не будет работать, если мы захотим

одновременно адаптировать класс и его подклассы
Позволяет адаптеру Adapter заместить некоторые операции адаптируемого класса Adaptee
Вводит только один новый объект
Для того, чтобы добраться до адаптируемого класса, не нужно дополнительного обращения по указателю
Отношения (адаптер класса)Адаптер класса адаптирует Adaptee к Target, перепоручая действия конкретному классу AdapteeЭтот паттерн не будет работать,

Слайд 38Отношения (адаптер объектов)
Позволяет одному адаптеру Adapter работать со многими адаптируемыми

объектами Adaptee
С самим Adaptee и его подклассами при их наличии
Адаптер

может добавить новую функциональность сразу всем адаптируемым объектам
Затрудняет замещение операций класса Adaptee
Для этого необходимо породить от Adaptee подкласс и заставить Adapter ссылаться на этот подкласса, а не на сам Adaptee
Отношения (адаптер объектов)Позволяет одному адаптеру Adapter работать со многими адаптируемыми объектами AdapteeС самим Adaptee и его подклассами

Слайд 39Вопросы, которые необходимо иметь в виду
Объем работы
Зависит от того, насколько

сильно различаются интерфейсы целевого и адаптируемого классов
Сменные адаптеры
Решается путем адаптации

интерфейсов
Использование двусторонних адаптеров для обеспечения прозрачности
Полезны в тех случаях, когда необходимо клиенту необходимо видеть как адаптируемый, так и целевой объект
Вопросы, которые необходимо иметь в видуОбъем работыЗависит от того, насколько сильно различаются интерфейсы целевого и адаптируемого классовСменные

Слайд 40Реализация адаптеров классов
В C++ Adapter должен открыто наследоваться от Target

и закрыто – от Adaptee
Adapter – подтип Target, но не

Adaptee

class CTarget
{
public:
virtual void DoSomething() = 0;
};
class CAdaptee
{
public:
void DoSomethingGood();
};
class CAdapter : public CTarget, private CAdaptee
{
public:
virtual void DoSometing()
{
DoSomethingGood();
}
};

Реализация адаптеров классовВ C++ Adapter должен открыто наследоваться от Target и закрыто – от AdapteeAdapter – подтип

Слайд 41Пример – иерархия графических объектов
class CPoint
{
public:
int x, int y
};
class CShape
{
public:
virtual

void GetBoundingBox(CPoint & bottomLeft, CPoint & topRight)const
};

class CTextView
{
public:
int GetLeft()const;
int GetTop()const;
int

GetWidth()const;
int GetHeight()const;
};

Задача – добавить в иерархию класс CTextShape (наследник CShape), используя функциональность класса CTextView

Пример – иерархия графических объектовclass CPoint{public:	int x, int y};class CShape{public:	virtual void GetBoundingBox(CPoint & bottomLeft, CPoint & topRight)const};class

Слайд 42Решение
class CPoint
{
public:

int x, int y
};
class CShape // целевой объект
{
public:
virtual void GetBoundingBox(CPoint

& bottomLeft, CPoint & topRight)const;
};

class CTextView {…}; // адаптируемый класс

// адаптер
class

CTextShape : public CShape, private CTextView
{
public:
virtual void GetBoundingBox(CPoint & bottomLeft, CPoint & topRight)const
{
bottomLeft.x = GetLeft();
bottomLeft.y = GetTop() + GetHeight();
topRight.x = GetLeft() + GetWidth();
topRight.y = GetTop();
}
};
Решениеclass CPoint{public:	…	int x, int y};class CShape	// целевой объект{public:	virtual void GetBoundingBox(CPoint & bottomLeft, CPoint & topRight)const;};class CTextView {…};	//

Слайд 43Реализация сменных адаптеров
Задача – разработать компонент CTreeDisplay для визуализации древовидных

структур
Иерархии классов
Дерево папок
Иерархии живых организмов
Для разных типов структур нужны разные

операци доступа к потомкам:
GetSubclasses для классов, GetSubdirectories для файловой системы, и т.п.
Компонент CTreeDisplay должен уметь отображать иерархии обоих видов даже если у них разные интерфейсы
Реализация сменных адаптеровЗадача – разработать компонент CTreeDisplay для визуализации древовидных структурИерархии классовДерево папокИерархии живых организмовДля разных типов

Слайд 44Реализация сменных адаптеров
Шаг 1. Поиск «узкого» интерфейса для Adaptee
Наименьшее подмножество

операций, позволяющее выполнить адаптацию
Минимальный интерфейс для CTreeDisplay может включать всего

две операции
Получить графическое представление узла
Доступ к потомкам узла
Шаг 2. Выбор одного из следующих подходов к реализации
Использование абстрактных операций
Использование объектов-уполномоченных
Реализация сменных адаптеровШаг 1. Поиск «узкого» интерфейса для AdapteeНаименьшее подмножество операций, позволяющее выполнить адаптациюМинимальный интерфейс для CTreeDisplay

Слайд 45Подход 1 – «Использование абстрактных операций»
Определим в классе CTreeDisplay абстрактные

операции, соответствующие узкому интерфейсу класса Adaptee
Подклассы CTreeDisplay реализовывают данные операции

и адаптируют иерархически структурированный объект
Класс CDirectoryTreeDisplay будет осуществлять доступ к структуре каталогов файловой системы
Класс CDirectoryTreeDisplay специализирует узкий интерфейс таким образом, чтобы он мог отображать структуру каталогов, составленную из объектов CFileSystemEntity
Подход 1 – «Использование абстрактных операций»Определим в классе CTreeDisplay абстрактные операции, соответствующие узкому интерфейсу класса AdapteeПодклассы CTreeDisplay

Слайд 46Структура
CTreeDisplay (Client, Target)
GetChildren(CNode)
CreateGraphicNode(CNode)
Display()
BuildTree(Node n)

DirectoryTreeDisplay (Adapter)
GetChildren(Node)
CreateGraphicNode(Node)
CFileSystemEntity (Adaptee)

GetChildren(n)
Для каждого потомка {
AddGraphicNode(CreateGraphicNode(child))
BuildTree(child)
}

СтруктураCTreeDisplay (Client, Target)GetChildren(CNode)CreateGraphicNode(CNode)Display()BuildTree(Node n)DirectoryTreeDisplay (Adapter)GetChildren(Node)CreateGraphicNode(Node)CFileSystemEntity (Adaptee)GetChildren(n)Для каждого потомка {	AddGraphicNode(CreateGraphicNode(child))	BuildTree(child)}

Слайд 47Подход 2 – «Использование объектов-уполномоченных»
CTreeDisplay выполняет переадресацию запросов к иерархической

структуре объекту-уполномоченному
Узкий интерфейс объекта-уполномоченного (Целевой объект) помещается в абстрактный класс

CTreeAccessorDelegate
Класс CDirectoryBrowser (Адаптер) наследуется от CTreeAccessorDelegate, реализуя абстрактные операции уполномоченного объекта
Подход 2 – «Использование объектов-уполномоченных»CTreeDisplay выполняет переадресацию запросов к иерархической структуре объекту-уполномоченномуУзкий интерфейс объекта-уполномоченного (Целевой объект) помещается

Слайд 48Структура
CTreeDisplay (Client)
SetDelegate(CTreeAccessorDelegate)
Display()
BuildTree(Node n)

delegate->GetChildren(this, n)
Для каждого потомка {
AddGraphicNode(
delegate->CreateGraphicNode(this, child))
BuildTree(child)
}
CTreeAccessorDelegate (Target)
GetChildren(CTreeDisplay, Node)
CreateGraphicNode(CTreeDisplay,

Node)
CDirectoryBrowser (Adapter)
GetChildren(CTreeDisplay, Node)
CreateGraphicNode(CTreeDisplay, Node)
CreateFile()
DeleteFile()

CFileSystemEntity (Adaptee)

delegate

СтруктураCTreeDisplay (Client)SetDelegate(CTreeAccessorDelegate)Display()BuildTree(Node n)delegate->GetChildren(this, n)Для каждого потомка {	AddGraphicNode(		delegate->CreateGraphicNode(this, child))	BuildTree(child)}CTreeAccessorDelegate (Target)GetChildren(CTreeDisplay, Node)CreateGraphicNode(CTreeDisplay, Node)CDirectoryBrowser (Adapter)GetChildren(CTreeDisplay, Node)CreateGraphicNode(CTreeDisplay, Node)CreateFile()DeleteFile()CFileSystemEntity (Adaptee)delegate

Обратная связь

Если не удалось найти и скачать доклад-презентацию, Вы можете заказать его на нашем сайте. Мы постараемся найти нужный Вам материал и отправим по электронной почте. Не стесняйтесь обращаться к нам, если у вас возникли вопросы или пожелания:

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика