Перечень порождающих паттернов — КиберПедия 

Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...

Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого...

Перечень порождающих паттернов

2019-08-07 127
Перечень порождающих паттернов 0.00 из 5.00 0 оценок
Заказать работу

К порождающим паттернам проектирования относятся следующие:

· абстрактная фабрика (abstract factory);

· строитель (builder);

· фабричный метод (factory method);

· прототип (prototype);

· одиночка (singleton)

 

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

Абстрактная фабрика — паттерн позволяющий изменять поведение системы, варьируя создаваемые объекты, при этом сохраняя интерфейсы. Он позволяет создавать целые группы взаимосвязанных объектов (продуктов), которые, будучи созданными одной фабрикой, реализуют общее поведение. Паттерн реализуется созданием абстрактного класса Factory, который представляет собой интерфейс для создания компонентов системы (например, для оконного интерфейса он может создавать окна, кнопки и т.д.). Затем пишутся наследующиеся от него классы, реализующие этот интерфейс. Иначе говоря, продукт это тот объект, который должен быть произведен, а фабрика предоставляет механизм для его создания.

 

Назначение

Предоставляет интерфейс для создания семейств, взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов.

Достоинства

· изолирует конкретные классы;

  • упрощает замену семейств продуктов;
  • гарантирует сочетаемость продуктов.

 

Недостатки

· сложно добавить поддержку нового вида продуктов.

Применение

· Система не должна зависеть от того, как создаются, компонуются и представляются входящие в нее объекты.

· Входящие в семейство взаимосвязанные объекты должны использоваться вместе и вам необходимо обеспечить выполнение этого ограничения.

· Система должна конфигурироваться одним из семейств составляющих ее объектов.

· Требуется предоставить библиотеку объектов, раскрывая только их интерфейсы, но не реализацию.

 

 

    При данной реализации клиент не должен знать ничего о конкретных классах. Он только запрашивает у фабрики (абстрактной) построение объекта (абстрактного) с соответствующим интерфейсом.

 

Пример

#include <iostream>

 

// Абстрактный ProductA

class Car

{ public:

virtual void info() = 0;

virtual ~Car(){}

};

 

// Конкретный ProductA1

class Ford: public Car

{ public:

virtual void info()

{ std::cout << "Ford" << std::endl; }

};

 

// Конкретный ProductA2

class Toyota: public Car

{ public:

virtual void info()

{ std::cout << "Toyota" << std::endl; }

};

 

// Абстрактный ProductВ

class Engine

{ public:

virtual void getPower() = 0;

virtual ~Engine(){}

};

 

// Конкретный ProductB1

class FordEngine: public Engine

{ public:

virtual void getPower()

{ std::cout << "Ford Engine 4.4" << std::endl; }

};

 

// Конкретный ProductB2

class ToyotaEngine: public Engine

{ public:

virtual void getPower()

{ std::cout << "Toyota Engine 3.2" << std::endl; }

};

 

 

// AbstractFactory

class CarFactory

{ public:

Car* getNewCar()

{ return createCar(); }

 

Engine* getNewEngine()

{ return createEngine(); }

 

virtual ~ CarFactory(){}

protected:

virtual Car*  createCar() = 0;

virtual Engine* createEngine() = 0;

};

 

// Конкретная Factory1

class FordFactory: public CarFactory

{ protected:

// from CarFactory

virtual Car* createCar()

{ return new Ford(); }

 

virtual Engine* createEngine()

{ return new FordEngine(); }

};

 

// Конкретная Factory2

class ToyotaFactory: public CarFactory

{ protected:

// from CarFactory

virtual Car* createCar()

{ return new Toyota(); }

 

virtual Engine* createEngine()

{ return new ToyotaEngine(); }

};

 

int main()

{

CarFactory* curFactory = NULL;

Car* myCar    = NULL;

Engine* myEngine = NULL;

 

ToyotaFactory toyotaFactory;

FordFactory   fordFactory;

 

curFactory = &toyotaFactory;

 

myCar = curFactory->getNewCar();

myCar->info();

myEngine = curFactory->getNewEngine();

myEngine->getPower();

delete myCar;

delete myEngine;

 

 

curFactory = &fordFactory;

myCar = curFactory->getNewCar();

myCar->info();

myEngine = curFactory->getNewEngine();

myEngine->getPower();

delete myCar;

delete myEngine;

return 0;

}

 

 

Строитель

Назначение

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

Недостатки

· позволяет изменять внутреннее представление продукта;

· изолирует код, реализующий конструирование и представление;

· дает более тонкий контроль над процессом конструирования.

Применение

· алгоритм создания сложного объекта не должен зависеть от того, из каких частей состоит объект и как они стыкуются между собой;

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

 

 

Пример

 

#include <iostream>

#include <memory>

#include <string>

 

// Product

class Pizza

{

private:

std::string dough; //

std::string sauce; // соус

std::string topping; //

 

public:

Pizza() { }

~Pizza() { }

 

void SetDough(const std::string& d) { dough = d; };

void SetSauce(const std::string& s) { sauce = s; };

void SetTopping(const std::string& t) { topping = t; }

 

void ShowPizza()

{

   std::cout << " Yummy!!!" << std::endl

   << "Pizza with Dough as " << dough

   << ", Sauce as " << sauce

   << " and Topping as " << topping

   << "!!! " << std::endl;

}

};

 

// Abstract Builder

class PizzaBuilder

{

protected:

std::auto_ptr<Pizza> pizza;

public:

PizzaBuilder() {}

virtual ~PizzaBuilder() {}

std::auto_ptr<Pizza> GetPizza() { return pizza; }

 

void createNewPizzaProduct() { pizza.reset (new Pizza); }

 

virtual void buildDough()=0;

virtual void buildSauce()=0;

virtual void buildTopping()=0;

};

 

// ConcreteBuilder

class HawaiianPizzaBuilder: public PizzaBuilder

{

public:

HawaiianPizzaBuilder(): PizzaBuilder() {}

~HawaiianPizzaBuilder(){}

 

void buildDough() { pizza->SetDough("cross"); }

void buildSauce() { pizza->SetSauce("mild"); }

void buildTopping() { pizza->SetTopping("ham and pineapple"); }

};

 

// ConcreteBuilder

class SpicyPizzaBuilder: public PizzaBuilder

{

public:

SpicyPizzaBuilder(): PizzaBuilder() {}

 ~SpicyPizzaBuilder() {}

 

void buildDough() { pizza->SetDough("pan baked"); }

void buildSauce() { pizza->SetSauce("hot"); }

void buildTopping() { pizza->SetTopping("pepperoni and salami"); }

};

 

// Director

class Waiter

{

private:

PizzaBuilder* pizzaBuilder;

public:

Waiter(): pizzaBuilder(NULL) {}

~Waiter() { }

 

void SetPizzaBuilder(PizzaBuilder* b) { pizzaBuilder = b; }

std::auto_ptr<Pizza> GetPizza() { return pizzaBuilder->GetPizza(); }

void ConstructPizza()

{

   pizzaBuilder->createNewPizzaProduct();

   pizzaBuilder->buildDough();

   pizzaBuilder->buildSauce();

   pizzaBuilder->buildTopping();

}

};

 

// Клиент заказывает две пиццы.

int main()

{

Waiter waiter;

 

HawaiianPizzaBuilder hawaiianPizzaBuilder;

waiter.SetPizzaBuilder (&hawaiianPizzaBuilder);

waiter.ConstructPizza();

std::auto_ptr<Pizza> pizza = waiter.GetPizza();

pizza->ShowPizza();

 

SpicyPizzaBuilder spicyPizzaBuilder;

waiter.SetPizzaBuilder(&spicyPizzaBuilder);

waiter.ConstructPizza();

pizza = waiter.GetPizza();

pizza->ShowPizza();

 

return EXIT_SUCCESS;

}

 

 

 

Фабричный метод

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

 

Назначение

Определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс инстанциировать. Фабричный метод позволяет классу делегировать создание подклассам. Используется, когда:

· классу заранее неизвестно, объекты каких подклассов ему нужно создавать.

· класс спроектирован так, чтобы объекты, которые он создаёт, специфицировались подклассами.

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

 

Структура

 

  • Product - продукт

- определяет интерфейс объектов, создаваемых абстрактным методом;

  • ConcreteProduct - конкретный продукт

- реализует интерфейс Product;

  • Creator - создатель

- объявляет фабричный метод, который возвращает объект типа Product. Может также содержать реализацию этого метода "по умолчанию";

- может вызывать фабричный метод для создания объекта типа Product;

  • ConcreteCreator - конкретный создатель

- переопределяет фабричный метод таким образом, чтобы он создавал и возвращал объект класса ConcreteProduct.

Достоинства

  • позволяет сделать код создания объектов более универсальным, не привязываясь к конкретным классам (ConcreteProduct), а оперируя лишь общим интерфейсом (Product);
  • позволяет установить связь между параллельными иерархиями классов.

Недостатки

  • необходимость создавать наследника Creator для каждого нового типа продукта (ConcreteProduct).

Пример

 

#include<iostream>

#include<string>

using namespace std;

 

// Product

class Product

{ public:

virtual string getName() = 0;

virtual ~Product(){};

 

// ConcreteProductA

class ConcreteProductA: public Product

{ public:

string getName()

{ return "ConcreteProductA"; }

};

 

// ConcreteProductB

class ConcreteProductB: public Product

{ public:

string getName()

{ return "ConcreteProductB"; }

};

 

// Creator

class Creator

{ public:

virtual Product* FactoryMethod() = 0;

virtual ~ Creator (){};

};

 

// ConcreteCreatorA

class ConcreteCreatorA: public Creator

{ public:

Product* FactoryMethod()

{ return new ConcreteProductA(); }

};

 

// ConcreteCreatorB

class ConcreteCreatorB: public Creator

{ public:

Product* FactoryMethod()

{ return new ConcreteProductB(); }

};

 

int main()

{ const int size = 2;

// Создание массива конкретных creators

Creator* creators[size];

creators[0] = new ConcreteCreatorA();

creators[1] = new ConcreteCreatorB();   

 

// Для каждого из creators создание своего product

for(int i=0; i<size; i++)

{ Product* product = creators[i]->FactoryMethod();

cout<<product->getName()<<endl;

   delete product;

}

 

for(int i=0; i<size; i++) delete creators[i];

return 0;

}

 

 

Прототип

Назначение

Задаёт виды создаваемых объектов с помощью экземпляра-прототипа и создаёт новые объекты путём копирования этого прототипа...

Применимость

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

  • инстанцируемые классы определяются во время выполнения, например с помощью динамической загрузки;
  • для того чтобы избежать построения иерархий классов или фабрик, параллельных иерархии классов продуктов;
  • экземпляры класса могут находиться в одном из нескольких различных состояний. Может оказаться удобнее установить соответствующее число прототипов и клонировать их, а не инстанцировать каждый раз класс вручную в подходящем состоянии.

 

 

Пример

Одиночка

Цель

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

Достоинства

  • контролируемый доступ к единственному экземпляру;
  • уменьшение числа имён;
  • допускает уточнение операций и представления;
  • допускает переменное число экземпляров;
  • большая гибкость, чем у операций класса.

Недостатки

  • Глобальные объекты могут быть вредны для объектного программирования, в некоторых случаях приводя к созданию немасштабируемого проекта.

Применение

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

Пример

Возможная реализация на C++ (известная как синглтон Мейерса), где одиночка представляет собой статический локальный объект (важно: это решение не потоко-безопасно и приводится только для того, чтобы показать как устроен шаблон, а не для реального использования в крупномасштабных программных проектах. Кроме того, данная реализация не обеспечивает невозможность создать еще один экземпляр класса).

 

 template<typename T> class Singleton

 {

 

public:

static T& Instance()

{

    static T theSingleInstance; // у класса T есть конструктор по

                                // умолчанию

    return theSingleInstance;

 }

 };

 

 class OnlyOne: public Singleton<OnlyOne>

 {

//.. интерфейс класса

 };

Синглтон на диаграмме классов

 

=====================================================


Поделиться с друзьями:

История развития пистолетов-пулеметов: Предпосылкой для возникновения пистолетов-пулеметов послужила давняя тенденция тяготения винтовок...

Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...

Своеобразие русской архитектуры: Основной материал – дерево – быстрота постройки, но недолговечность и необходимость деления...

Особенности сооружения опор в сложных условиях: Сооружение ВЛ в районах с суровыми климатическими и тяжелыми геологическими условиями...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.098 с.