Проектирование программных систем. Занятие 9

42
МАИ, каф 806, ППС 1 Паттерны проектирования улучшение модифицируемости решения Паттерн это описание задачи и её типового решения Состоит: Имя Постановка задачи Описание решения Описания когда данный паттерн необходимо применять Примера

Upload: dima-dzuba

Post on 21-Nov-2014

814 views

Category:

Education


2 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС1

Паттерны проектированияулучшение модифицируемости решения

Паттерн – это описание задачи и её типового решения

Состоит:

Имя

Постановка задачи

Описание решения

Описания когда данный паттерн необходимо применять

Примера

Page 2: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

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

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

Они помогают:

Быстро сфокусироваться на решении проблемы, как только вы распознали нужный паттерн.

Изучение паттернов помогает придти к новым идеям.

Предоставить единый язык для дискуссий.

Предоставить решение проблем из реального мира.

Объяснить причину, по которой выбирается решение.

Многократно использовать опыт предыдущих поколений дизайнеров систем.

Но:

Паттерны не содержат ответы на все вопросы и решения всех задач!

Неправильно идентифицированный и примененный паттерн доставит больше неприятности, чем пользы.

2

Page 3: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияСоздание объектов

Описывают способы как можно создавать объекты в программе.

Борется с основным видом зависимости между модулями – знанием о существовании модуля и месте расположения.

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

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

Паттерны:

Abstract Factory

Builder

Factory Method

Prototype

Singleton

3

Page 4: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС4

Паттерны проектированияСоздание объектов/Abstract Factory

Описание задачи

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

Описание решения

Создание отдельного класса отвечающего за создание экземпляров объектов.

Когда применять

Можно выделить группы схожих объектов. Т.е. в одном случае мы создаем один набор объектов (одной фабрикой) в другом случае другой набор объектов (другой фабрикой)

Пример

Интерфейс пользователя с набором «скинов». Т.е. набор различных по отображению интерфейсов но с одинаковой функциональностью.

Доступ к базе данных (когда для разных СУБД есть разные объекты доступа)

Page 5: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияСоздание объектов/Abstract Factory

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

ConcreteFactory - конкретная фабрика:реализует операции, создающие конкретные объекты-продукты;

AbstractProduct - абстрактный продукт:объявляет интерфейс для типа объекта-продукта;

ConcreteProduct - конкретный продукт:определяет объект-продукт, создаваемый соответствующей конкретной фабрикой и реализует интерфейс Abstract Product;

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

5

Page 6: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияСоздание объектов/Abstract Factory

6

Так это выглядит в жизни

Page 7: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияСоздание объектов/Abstract Factory

interface MazeFactory {

Maze MakeMaze();

Wall MakeWall();

Room MakeRoom(int n);

Door MakeDoor(Room rl, Room r2);

};

Maze CreateMaze (MazeFactory factory)

{

Maze aMaze = factory.MakeMaze();

Room rl = factory.MakeRoom(l);

Room r2 = factory.MakeRoom(2);

Door aDoor = factory.MakeDoor(rl, r2);

aMaze.AddRoom(rl) ;

aMaze.AddRoom(r2);

rl.SetSide(North, factory.MakeWall());

rl.SetSide(East, aDoor);

rl.SetSide(South, factory.MakeWall() ) ;

rl.SetSide(West, factory.MakeWall());

r2.SetSide(North, factory.MakeWall());

r2.SetSide(East, factory.MakeWall());

r2.SetSide(South, factory.MakeWall());

r2.SetSide(West, aDoor);

return aMaze;

}

7

Page 8: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС8

Паттерны проектированиясоздание объектов/ builder

Описание задачи

Необходимо конструировать сложные объекты. При этом объекты со схожей конструкцией могут создаваться из разных объектов.

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

Когда применять

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

Пример

Преобразование форматов, когда нужно применить последовательно серию преобразований. Например при переводе текста из одного формата в другой мы последовательно применяем наборы преобразований параграфов, слов, шрифтов …

Page 9: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированиясоздание объектов/ builder

Паттерн реализует конвейер

9

Page 10: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированиясоздание объектов/ builder / пример

interface MazeBuilder

{

void BuildMaze();

void BuildRoom(int room);

void BuildDoor(int roomFrom, int roomTo);

Maze GetMaze();

};

Maze CreateMaze (MazeBuilder builder)

{

builder.BuildMaze();

builder.BuiIdRoom(l);

builder.BuiIdRoom(2) ;

builder.BuildDoor(1, 2);

return builder.GetMaze();

}

10

Page 11: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС11

Паттерны проектированияcоздание объектов / Factory Method

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

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

Когда применятьХорошо все вызовы new оформлять в виде отдельных методов, где это возможно.

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

Page 12: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияcоздание объектов / Factory Method

Две основных разновидности паттерна.

Во-первых, это случай, когда класс Сгeator'является абстрактным и не содержит реализации объявленного в нем фабричного метода.

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

Параметризованные фабричные методы.

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

12

Page 13: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияcоздание объектов / Factory Method / Пример

package j2ee.architect.FactoryMethod;public class FactoryMethodPattern {public static void main(String[] args) {// Create creator, which uses the

FactoryMethodCreatorIF creator = new ConcreteCreator();// Create trade via factory methodTradeIF trade = creator.factoryMethod();// Call trade action methodtrade.action();System.out.println();

}}

public class ConcreteCreator implements CreatorIF {public TradeIF factoryMethod() {return new ConcreteTrade();

}}

public class ConcreteTrade implements TradeIF {public void action() {System.out.println("ConcreteTrade.action() called.");

}}

public interface CreatorIF {public abstract TradeIF factoryMethod();

}

public interface TradeIF {public void action();

}

13

Page 14: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС14

Паттерны проектирования. создание объектов/ Prototype

Описание задачиНеобходимо создавать объект «по образцу».

Описание решенияУ объектов, требующих копирование создается метод Clone дублирующий объект.

Когда применятьМного объектов требующих создание по образцу или жесткие требования к модифицируемости программы.

ПримерГрафический редактор, где на палитре

«инструментов» размещаются объекты. При помещении из в рабочее поле создаются копии объектов с палитры.

Page 15: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектирования. создание объектов/ Prototype

Варианты реализации

использование диспетчера прототипов.

реализация операции Clone.

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

добавление и удаление продуктов во время выполнения.

спецификация новых объектов путем изменения значений.

Недостатки

Основной недостаток паттерна прототип заключается в том, что каждый подкласс класса Prototype должен реализовывать операцию Clone, а это далеко не всегда просто. Например, сложно добавить операцию Clone, когда рассматриваемые классы уже существуют.

Проблемы возникают и в случае, если во внутреннем представлении объекта есть другие объекты или наличествуют круговые ссылки

15

Page 16: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектирования. создание объектов/ Prototype

Клонирование человека запрещено! С программными объектами – все проще.

16

Page 17: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированиясоздание объектов / Prototype /Пример

public class PrototypePattern {public static void main(String[] args) {

// Create prototypesSystem.out.println("Constructing prototypes.");PrototypeIF prototype1 = new ConcretePrototype1();PrototypeIF prototype2 = new ConcretePrototype2();

// Get clones from prototypesSystem.out.println("Constructing clones from

prototypes.");PrototypeIF clone1 = prototype1.getClone();PrototypeIF clone2 = prototype2.getClone();

// Call actions on the clonesSystem.out.println("Calling actions on the clones.");clone1.action();clone2.action();System.out.println();

}}

public class ConcretePrototype1 implements PrototypeIF {public ConcretePrototype1() {System.out.println("ConcretePrototype1 constructed.");

}public PrototypeIF getClone() {return new ConcretePrototype1();

}public void action() {System.out.println("ConcretePrototype1.action()

called");}

}

public class ConcretePrototype2 implements PrototypeIF {public ConcretePrototype2() {System.out.println("ConcretePrototype2 constructed.");

}public PrototypeIF getClone() {return new ConcretePrototype1();

}public void action() {System.out.println("ConcretePrototype2.action()

called.");}

}

public interface PrototypeIF {public PrototypeIF getClone(); public void action();

}

17

Page 18: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС18

Паттерны проектированиясоздание объектов/ Singleton

Описание задачиВ программе существуют глобальные объекты с одним экземпляром на всю программу.

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

Когда применятьВсегда когда нужно хранить глобальные свойства системы или иметь доступ к глобальному ресурсу (если он может существовать только в одном экземпляре)

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

Page 19: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированиясоздание объектов/ Singleton

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

контролируемый доступ к единственному экземпляру.

уменьшение числа имен, используемых в системе.

допускает уточнение операций и представления.

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

большая гибкость, чем у операций класса.

Реализация

гарантирование единственного экземпляра.

порождение подклассов Singleton (при необходимости).

19

Page 20: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированиясоздание объектов/ Singleton

Должен остаться только один!

20

Page 21: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированиясоздание объектов / Singleton /Пример

public class SingletonPattern {public static void main(String[] args) {

Singleton s1 = Singleton.getInstance();System.out.println("s1.getInfo()="+ s1.getInfo());

Singleton s2 = Singleton.getInstance();System.out.println("s2.getInfo()="+s2.getInfo());System.out.println("s1.setValue(42)");s1.setValue(42);

System.out.println("s1.getValue()="+s1.getValue());System.out.println("s2.getValue()="+s2.getValue());System.out.println("s1.equals(s2)="+s1.equals(s2)+ ", s2.equals(s1)="+s2.equals(s1));

System.out.println();}

}

public final class Singleton {private static Singleton instance;private int value;private Singleton()

{

System.out.println("Singleton constructed.");

}public static synchronized Singleton getInstance()

{if (instance == null)instance = new Singleton();

return instance;}

public String getInfo() {return getClass().getName() +// Uncomment line below to also see the loader//+", loaded by " + getClass().getClassLoader();", id#" + System.identityHashCode(this);

}public int getValue() {return value;}public void setValue(int parm) {value = parm;}public boolean equals(Singleton parm) {return (System.identityHashCode(this)== System.identityHashCode(parm));

}}

21

Page 22: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

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

Предназначены для организации сложных структур объектов.

Помогают упростить работу со сложными структурами.

Включают:

Adapter

Bridge

Composite

Decorator

Facade

Flyweight

Proxy

22

Page 23: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС23

Паттерны проектирования. Структурные паттерны

Adapter Описание задачи

Существует необходимость использовать для решения задачи класс с отличной от изначально спроектированной структуры.

Описание решения

Создается специальный адаптер для конвертации интерфейсов.

Когда применять

Когда проще сделать адаптер, чем переписать остальную систему на использование нового интерфейса.

Пример

Для доступа к БД использовался механизм ODBC, но понадобилось использовать новую БД для которой есть только ADO интерфейс.

Page 24: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС24

Паттерны проектирования. Структурные паттерныадаптер

С одной стороны 220 вольт, а с другой – столько сколько нужно!

Page 25: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияструктурные паттерны/ Adapter / пример

public class AdapterPattern {

public static void main(String[] args) {

// Create targets.

System.out.println("Creating targets.");

TargetIF target1 = new AdapterByClass();

TargetIF target2 = new AdapterByObject();

// Call target requests

System.out.println("Calling targets.");

System.out.println("target1.newRequest()->"+target1.newRequest());

System.out.println("target2.newRequest()->"+target2.newRequest());

System.out.println();

}

}

public class Adaptee {

public Adaptee() {

System.out.println("Adaptee constructed.");

}

public String oldRequest() {

return "Adaptee.oldRequest() called.";

}

}

public class AdapterByClass extends Adaptee implements TargetIF {

public AdapterByClass() {

System.out.println("AdapterByClass constructed.");

}

public String newRequest() {

return oldRequest();

}

}

public class AdapterByObject implements TargetIF {

private Adaptee adaptee;

public AdapterByObject() {

System.out.println("AdapterByObject constructed.");

}

public String newRequest() {

// Create an Adaptee object if it doesn’t exist yet

if (adaptee == null) { adaptee = new Adaptee(); }

return adaptee.oldRequest();

}

}

public interface TargetIF {

public String newRequest();

}

25

Page 26: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС26

Паттерны проектирования. Структурные паттерны

Bridge Описание задачи

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

Описание решения

Создается класс Abstraction с описанием сценария работы с конкретной реализацией абстракции.

Когда применять

Абстракция и реализация может развиваться независимо (например, в различных случаях может использоваться различная реализация)

Пример

При проектировании БД в интерфейсе была определена одна сущность, но при реализации она распалась на три таблицы в БД.

Page 27: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияструктурные паттерны/ Bridge/ пример

public class BridgePattern {

public static void main(String[] args) {

System.out.println("Constructing SportsCar and EconomyCar.");

AbstractionIF car1 = new SportsCar ();

AbstractionIF car2 = new EconomyCar();

car1.action();

car2.action();

}

}

public class SportsCarImplementor implements ImplementorIF {

public void actionImplemented()

{ System.out.println("SportsCarImplementor.actionImplemented() called.");

}

}

public class EconomyCarImplementor implements ImplementorIF {

public void actionImplemented() { System.out.println("EconomyCarImplementor.actionImplemented() called.");

}

}

public interface AbstractionIF {

public void action();

}

public interface ImplementorIF {

public void actionImplemented();

}

public class SportsCar implements AbstractionIF {

ImplementorIF implementor = new SportsCarImplementor();

public void action() {

implementor.actionImplemented();

}

}

public class EconomyCar implements AbstractionIF {

ImplementorIF implementor = new EconomyCarImplementor();

public void action() {

implementor.actionImplemented();

}

}

27

Page 28: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС28

Паттерны проектирования. Структурные паттерны

Composite Описание задачи

При работе с иерархичными объектами часто нужно иметь возможность работать с ними вне зависимости составной это объект или простой.

Описание решения

У всех объектов в иерархии выделяются как общие интерфейсы так и характерные только для сложных объектов.

Когда применять

Всегда при работе с динамическими структурами данных.

Пример

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

Page 29: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС29

Паттерны проектирования. Структурные паттерныComposite

Однотипно работаем с простыми и сложными объектами!

Page 30: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияструктурные паттерны/ Composite/ пример [1/2]

public class CompositePattern {

public static void main(String[] args) {

// Create leaves

Component leaf1 = new Leaf(" leaf#1");

Component leaf2 = new Leaf(" leaf#2");

Component leaf3 = new Leaf(" leaf#3");

// Create branches

Component branch1 = new Composite(" branch1");

Component branch2 = new Composite(" branch2");

// Create trunk

Component trunk = new Composite("trunk");

// Add leaf1 and leaf2 to branch1

branch1.add(leaf1);

branch1.add(leaf2);

// Add branch1 to trunk

trunk.add(branch1);

// Add leaf3 to branch2

branch2.add(leaf3);

// Add branch2 to trunk

trunk.add(branch2);

// Show trunk composition

System.out.println("Displaying trunk composition:");

trunk.display();

// Remove branch1 and branch2 from trunk

trunk.remove(branch1);

trunk.remove(branch2);

// Show trunk composition now

System.out.println("Displaying trunk composition now:");

trunk.display();

System.out.println();

}

}

30

Page 31: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияструктурные паттерны/ Composite/ пример [2/2]

public abstract class Component {

public abstract void display();

public void add(Component c) {}

public void remove(Component c) }

public Component getChild(int index) { return null; }

public String getName() { return null; }

}

package j2ee.architect.Composite;

public class Leaf extends Component {

private String name;

public Leaf(String parm) {

this.name = parm;

System.out.println(parm.trim()+" constructed.");

}

public void display() {

System.out.println(this.getName());

}

public String getName() {

return name;

}

}

import java.util.*;

public class Composite extends Component {

String name = null;

List children = new ArrayList();

public Composite(String parm) { this.name = parm;}

public String getName() { return name; }

public Component getChild(int parm) {

Component child;

try {child = (Component) children.get(parm);}

catch (IndexOutOfBoundsException ioobe) {child = null;}

return child; }

public void add(Component parm) {children.add(parm);}

public void remove(Component parm) {

try {

children.remove(parm);} catch (Exception e) {}

}

public void display() {

Iterator iterator = children.iterator();

System.out.println(this.getName()

+(iterator.hasNext()?" with the following: ":" that is bare."));

while (iterator.hasNext()) {((Component) iterator.next()).display();}

}

}

31

Page 32: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС32

Паттерны проектирования. Структурные паттерны

Decorator Описание задачи

Иногда появляется необходимость менять свойства объектов не на стадии проектирования, а на стадии выполнения.

Описание решения

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

Когда применять

Если существует много способов для реализации одного и того же действия (в зависимости от разных условий).

ПримерРабота с потоками ввода-вывода в Java.

Page 33: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияструктурные паттерны/ Decorator/ пример

public class DecoratorPattern {

public static void main(String[] args) {

// Create object decorated with A

System.out.println("Creating component decorated with A.");

ComponentIF decorated1 = new ConcreteDecoratorA();

decorated1.action();

// Create object decorated with B

ComponentIF decorated2 = new ConcreteDecoratorB();

// Call action on object decorated with B

System.out.println("Calling action() on component decorated with B.");

decorated2.action();

System.out.println();

}

}

public class ConcreteComponent implements ComponentIF {

public void action() {

System.out.println("ConcreteComponent.action() called.");

}

}

public class ConcreteDecoratorA extends Decorator {

String addedVariable;

public void action() {

super.action();

addedVariable = "extra";

System.out.println("ConcreteDecoratorA.addedVariable="+addedVariable);

}

}

public class ConcreteDecoratorB extends Decorator {

public void action() {

super.action();

addedMethod();

}

private void addedMethod() {

System.out.println("ConcreteDecoratorB.addedMethod() called.");

}

}

public class Decorator implements ComponentIF {

ComponentIF component = new ConcreteComponent();

public void action() {

component.action();

}

}

33

Page 34: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС34

Паттерны проектирования. Структурные паттерны

Facade Описание задачи

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

Описание решения

Создается класс-фасад, который скрывает внутреннее устройство системы.

Когда применять

Всегда. Если необходимо предоставить интерфейсы внешней системе.

Пример

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

Page 35: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияструктурные паттерны/ Façade / пример

public class FacadePattern {

public static void main(String[] args) {

// Construct and call Façade

System.out.println("Constructing facade.");

Façade façade = new Façade();

System.out.println("Calling facade.processOrder().");

façade.processOrder();

System.out.println();

}

}

public class Façade {

public void processOrder() {

SubSystem1 subsys1 = new SubSystem1();

subsys1.getCustomer();

subsys1.getSecurity();

subsys1.priceTransaction();

SubSystemN subsysN = new SubSystemN();

subsysN.checkBalances();

subsysN.completeOrder();

}

}

public class SubSystem1 {

public void getCustomer() {

System.out.println("SubSystem1.getCustomer() called.");}

public void getSecurity() {

System.out.println("SubSystem1.getSecurity() called.");}

public void priceTransaction() {

System.out.println("SubSystem1.priceTransaction() called.");}

}

public class SubSystemN {

public void checkBalances() {

System.out.println("SubSystemN.checkBalances() called.");}

public void completeOrder() {

System.out.println("SubSystemN.completeOrder() called.");}

}

35

Page 36: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС36

Паттерны проектирования.cтруктурные паттерны/ Flyweight

Описание задачи

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

Описание решения

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

Когда применять

В системе большое число объектов и стоимость хранения объектов достаточно большая (из-за числа или размера).

Пример

При реализации графического редактора контекст отображения –общее свойство, которое может быть вынесено наружу.

Page 37: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектирования.cтруктурные паттерны/ Flyweight

Применяйте этот паттерн, когда выполнены все нижеперечисленные условия:

в приложении используется большое число объектов;

из-за этого накладные расходы на хранение высоки;

большую часть состояния объектов можно вынести вовне;

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

приложение не зависит от идентичности объекта. Поскольку flyweight могут разделяться, то проверка на идентичность возвратит «истину≫для концептуально различных объектов;

37

Page 38: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияструктурные паттерны/ Flyweight / пример

public class FlyweightPattern {

public static void main(String[] args) {

// Create states

State stateF = new State(false);

State stateT = new State(true);

// Get reference to (and in doing so create) flyweight

FlyweightIF myfwkey1 = FlyweightFactory.getFlyweight("myfwkey");

// Get new reference to the same flyweight

FlyweightIF myfwkey2 = FlyweightFactory.getFlyweight("myfwkey");

// Call action on both references

System.out.println("Call flyweight action with state=false");

myfwkey1.action(stateF);

System.out.println("Call flyweight action with state=true");

myfwkey2.action(stateT);

System.out.println();

}

}

public class ConcreteFlyweight implements FlyweightIF {

private boolean state;

public ConcreteFlyweight(State parm) {

this.state = parm.getState();

}

public void action(State parm) {

System.out.println("ConcreteFlyweight.action("

+parm.getState()+") called.");

this.state = parm.getState();

System.out.println("ConcreteFlyweight.state = "

+ this.state);

}

}

public interface FlyweightIF {

// method to receive and act on extrinsic state.

public void action(State parm);

}

public class State {

private boolean state;

public State(boolean parm) {this.state = parm;}

public boolean getState() {return state;}

}

38

Page 39: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияструктурные паттерны/ Flyweight / пример

import java.util.*;

public class FlyweightFactory {

private static Map map = new HashMap();

public static FlyweightIF getFlyweight(String parm) {

// Return the Flyweight if it exists,

// or create it if it doesn’t.

FlyweightIF flyweight = null;

try {

if (map.containsKey(parm)) {

// Return existing flyweight

flyweight = (FlyweightIF) map.get(parm);

} else {

// Create flyweight with a ‘true’ state

flyweight = new ConcreteFlyweight(new State(true));

map.put(parm, flyweight);

System.out.println("Created flyweight "+parm+" with state=true");

System.out.println("");

}

} catch (ClassCastException cce) {

System.out.println(cce.getMessage());

}

return flyweight;

}

}

39

Page 40: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС40

Паттерны проектированияcтруктурные паттерны/ proxy

Описание задачи

Есть необходимость при выполнении действий над объектами проводить дополнительные процедуры (какие именно определяется только в процессе выполнения).

Описание решения

Делается объект-обертка с такими же интерфейсами.

Когда применять

Работа в разных адресных пространствах (Remoting), динамическое создание объектов, динамический подсчет ссылок на объекты и т.д.

Пример

Мониторинг вызовов к методам объекта. К каждому методу добавляется код с трассировками.

Page 41: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияcтруктурные паттерны/ proxy

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

виртуальный заместитель создает ≪тяжелые≫ объекты по требованию;

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

≪умная≫ ссылка это замена обычного указателя. Она позволяет выполнить дополнительные действия при доступе к объекту. К типичным применениям такой ссылки можно отнести:

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

загрузку объекта в память при первом обращении к нему;

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

41

Page 42: Проектирование программных систем. Занятие 9

МАИ, каф 806, ППС

Паттерны проектированияструктурные паттерны/ Proxy / пример

public class ProxyPattern {

public static void main(String[] args) {

// Create service proxy (instantiates service too)

System.out.println("Creating proxy to service.");

ServiceIF proxy = new Proxy();

// Call action method on service via proxy

System.out.println("Calling action method on proxy.");

proxy.action();

System.out.println();

}

}

public class Proxy implements ServiceIF {

// Proxy to be the service

private Service service = new Service();

public void action() {

service.action();

}

}

public class Service implements ServiceIF {

// Service to be proxied

public Service() {

System.out.println("Service constructed.");

}

public void action() {

System.out.println("Service.action() called.");

}

}

public interface ServiceIF {

// Interface for Service and Proxy

public void action();

}

42