Skip to content

ООП Лекция 13. Структурные паттерны.

Vladislav Mansurov edited this page May 10, 2022 · 8 revisions

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

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

Адаптер (Adapter)

Если одна сущность выполняет несколько ответственностей, надо разделять задачи => проблема дальнейшего развития. В случае если какая-то ответственность меняется, а другая нет, что делать? Надо разделять как в фабричном методе, любой порождающий паттерн надо выделять ответственного за принятия решений. Как быть?

Причины использования

Проблема, с которой мы сталкиваемся - это когда нам надо создавать объекты, и эти объекты в разных местах программы мы используем по-разному. Грубо говоря, один объект выступает в нескольких ролях. Из этого следует:

  • Для каждой роли используется свой интерфейс. В принципе, эти интерфейсы могу пересекаться. Но, если мы будем создавать такой класс, мы получим избыточный интерфейс.
  • Как правило, эти роли завязаны еще под ответственность. Один и тот же объект будет иметь несколько ответственностей, что с точки зрения ООП очень плохо. Каждый объект должен иметь только одну ответственностей.

Идея: У нас один и тот же объект выполняет несколько ролей, физически это один объект. В разных местах мы работаем с ним по-разному, т.е. разные интерфейсы. Выделить простой класс, а посредники будет представлять нужный класс для работы.

image

Реализуем понятие или сущность какую-то с простым интерфейсом, а любая работа через посредника идет, вот из диаграммы можно увидеть, что:

  • ConAdapterA - это одна роль объекта
  • ConAdapterB - это другая роль того же самого объекта и при изменении какой из них, другая не меняется. В разных частях программы по-разному работаем с эти объектом.

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

Примечание: Solution подобный => вырожденный Адаптер

Преимущества:

  • Он позволяет нам класс с любым интерфейсом использовать в нашей программе.
  • Позволяет не создавать нам классы с несколькими ответственностями. Разносим это по другим классам.

Недостатки:

  • Просто не понять без UML.
  • Дублирование кода (Кучу классов), нет мертвых классов.

Пример 1. Адаптер (Adapter).

# include <iostream>
# include <memory>

using namespace std;

class Adapter
{
public:
	virtual ~Adapter() = default;

	virtual void request() = 0;
};

class BaseAdaptee
{
public:
	virtual ~BaseAdaptee() = default;

	virtual void specificRequest() = 0;
};

class ConAdapter : public Adapter
{
private:
	shared_ptr<BaseAdaptee>  adaptee;

public:
	ConAdapter(shared_ptr<BaseAdaptee> ad) : adaptee(ad) {}

	virtual void request() override;
};

class ConAdaptee : public BaseAdaptee
{
public:
	virtual void specificRequest() override { cout << "Method ConAdaptee;" << endl; }
};

#pragma region Methods
void ConAdapter::request()
{
	cout << "Adapter: ";

	if (adaptee)
	{
		adaptee->specificRequest();
	}
	else
	{
		cout << "Empty!" << endl;
	}
}

#pragma endregion


int main()
{
	shared_ptr<BaseAdaptee> adaptee =  make_shared<ConAdaptee>();
	shared_ptr<Adapter> adapter = make_shared<ConAdapter>(adaptee);

	adapter->request();
}

Декоратор

Задача: избавиться от дублирования кода и большой иерархии

Декораторов может быть много

Можем продекорировать как одну сущность так и другую. Работать с декоратором будем работать как с компонентом, декоратор входит в общую иерархию

Возможно изменение объекта во время выполнения

Минусы

  • Долго выполняться

Композит или Компоновщик

Мост

Заместить (Proxy)

Фасад

Шаблоны и паттерны поведение

Их очень много, рассмотрим только основную часть

Clone this wiki locally