1. Паттерны для описания поведения объектов
Помогают быстро менять или расширять поведение программы.
Состоят из:
Chain of Responsibility
Command
Interpreter
Iterator
Mediator
Memento
Observer
State
Strategy
Template Method
Visitor
1 МАИ, каф 806, ППС
2. Паттерны проектирования
поведение объектов / Chain of Responsobility
Описание задачи
В системе необходимо обрабатывать
события сразу несколькими объектами.
Описание решения
Позволяет избежать привязки
отправителя запроса к его получателю,
давая шанс обработать запрос
нескольким объектам. Связывает
объекты-получатели в цепочку и
передает запрос вдоль этой цепочки,
пока его не обработают.
Когда применять
Когда необходимость дальнейшей
обработки событий определяет сам
обработчик а не внешняя сущность.
Пример
Обработка событий в
пользовательском интерфейсе.
2 МАИ, каф 806, ППС
4. Паттерны проектирования
поведение объектов / Chain of Responsobility
Результаты применения паттерна
ослабление связанности.
Этот паттерн освобождает объект от необходимости ≪знать≫, кто конкретно обработает
его запрос. Отправителю и получателю ничего неизвестно друг о друге, а включенному в
цепочку объекту - о структуре цепочки.
дополнительная гибкость при распределении обязанностей между объектами.
Цепочка обязанностей позволяет повысить гибкость распределения обязанностей между
объектами. Добавить или изменить обязанности по обработке запроса можно, включив в
цепочку новых участников или изменив ее каким-то другим образом.
получение не гарантировано.
Поскольку у запроса нет явного получателя, то нет и гарантий, что он вообще будет
обработан: он может достичь конца цепочки и пропасть. Необработанным запрос может
оказаться и в случае неправильной конфигурации цепочки.
4 МАИ, каф 806, ППС
5. Паттерны проектирования
поведение объектов / Chain of Responsobility
public class ChainOfResponsibilityPattern { public class Request {
public static void main(String[] args) { // The universe of known requests that can be handled.
try { public final static int EQUITY_ORDER = 100;
// Create Equity Order request. public final static int BOND_ORDER = 200;
Request equityOrderRequest = new // This objects type of request.
Request(Request.EQUITY_ORDER);
private int type;
System.out.println("Creating Bond Order request.");
public Request(int parm) throws Exception {
Request bondOrderRequest = new
// Validate the request type with the known universe.
Request(Request.BOND_ORDER);
if ((parm == EQUITY_ORDER) || (parm == BOND_ORDER))
// Create a request handler.
// Store this request type.
HandlerIF handler = new ConcreteHandler1();
this.type = parm;
// Process the Equity Order.
else
handler.processRequest(equityOrderRequest);
throw new Exception("Unknown Request type
// Process the Bond Order.
"+parm+".");
handler.processRequest(bondOrderRequest);
}
} catch (Exception e)
public int getType() {
{System.out.println(e.getMessage());}
return type;
System.out.println();
}
}
}
}
public interface HandlerIF {
public void processRequest(Request request);
}
5 МАИ, каф 806, ППС
6. Паттерны проектирования
поведение объектов / Chain of Responsobility
public class ConcreteHandler2 implements HandlerIF { public class ConcreteHandler1 implements HandlerIF {
public void processRequest(Request parm) { public void processRequest(Request parm) {
// You could add on to the processing chain here... // Start the processing chain here...
handleIt(parm); switch (parm.getType()) {
} case Request.EQUITY_ORDER: // This object processes
equity orders
private void handleIt(Request parm) {
handleIt(parm); // so call the function
System.out.println("ConcreteHandler2 has handled the
to handle it.
processing.");
break;
}
case Request.BOND_ORDER: // Another object
}
processes bond orders so
System.out.println("Creating 2nd handler."); //
pass request along.
new ConcreteHandler2().processRequest(parm);
break;
}
}
private void handleIt(Request parm) {
System.out.println("ConcreteHandler1 has handled the
processing.");
}
}
6 МАИ, каф 806, ППС
7. Паттерны проектирования
поведение объектов
Command
Описание задачи
В системе могут исполнятся команды,
при чем с возможностью определения
последовательности команд.
Описание решения
Выделяется базовый класс для всех
команд, с универсальным
интерфейсом запуска.
Когда применять
В системе большое число разнотипных
команд с которыми нужно работать по
одинаковым алгоритмам.
Пример
Команды в пользовательском
интерфейсе.
7 МАИ, каф 806, ППС
9. Паттерны проектирования
поведение объектов / command
public class CommandPattern { abstract class CommandAbstract {
public static void main(String[] args) { public abstract void execute();
System.out.println("Creating receivers."); }
ReceiverIF order = new Order();
ReceiverIF trade = new Trade(); public class ConcreteCommand extends CommandAbstract {
System.out.println("Creating commands."); // The binding between action and receiver
CommandAbstract cmdOrder = new private ReceiverIF receiver;
ConcreteCommand(order);
public ConcreteCommand(ReceiverIF receive) {
CommandAbstract cmdTrade = new
this.receiver = receive;
ConcreteCommand(trade);
}
System.out.println("Creating invokers.");
public void execute() {
Invoker invOrder = new Invoker();
receiver.action();
Invoker invTrade = new Invoker();
}
// Storing commands in invokers respectively.
}
System.out.println("Storing commands in invokers.");
public class Invoker {
invOrder.storeCommand(cmdOrder);
private CommandAbstract command;
invTrade.storeCommand(cmdTrade);
public void storeCommand(CommandAbstract cmd) {
// Call invoke on the invoker to execute the command.
this.command = cmd;
System.out.println("Invoking the invokers.");
}
invOrder.invoke();
public void invoke() {
invTrade.invoke();
command.execute();
System.out.println();
}
}
}
}
9 МАИ, каф 806, ППС
10. Паттерны проектирования
поведение объектов / command
public class Order implements ReceiverIF {
public void action() {
System.out.println("Order.action() called.");
}
}
public interface ReceiverIF {
public void action();
}
public class Trade implements ReceiverIF {
public void action() {
System.out.println("Trade.action() called.");
}
}
10 МАИ, каф 806, ППС
11. Паттерны проектирования
поведение объектов
Interpreter
Описание задачи
Необходимо осуществлять разбор
синтаксических выражений.
Описание решения
Правила организуются в виде иерархии
классов. Метод интерпретирует
выражение соответствующего классу
типа. Паттерн интерпретатор
использует класс для представления
каждого правила грамматики.
Когда применять
Когда грамматика не очень сложная.
Пример
Разбор простых текстовых команд с
регулярной структурой.
11 МАИ, каф 806, ППС
12. Паттерны проектирования
поведение объектов
Результаты применения паттерна
грамматику легко изменять и расширять.
Поскольку для представления грамматических правил в паттерне используются классы,
то для изменения или расширения грамматики можно применять наследование
простая реализация грамматики.
Реализации классов, описывающих узлы абстрактного синтаксического дерева, похожи.
добавление новых способов интерпретации выражений.
Паттерн интерпре татор позволяет легко изменить способ вычисления выражений.
12 МАИ, каф 806, ППС
13. Паттерны проектирования
поведение объектов /
import java.util.ArrayList; bookInterpreterContext.addTitleAndAuthor(
import java.util.ListIterator; new TitleAndAuthor("Great Expectations", "William
Shakespeare"));
import java.util.StringTokenizer;
bookInterpreterContext.addTitleAndAuthor(
public class InterpreterPattern {
new TitleAndAuthor("Wuthering Heights", "Emily
public static void main(String[] args) {
Bronte"));
BookInterpreterContext bookInterpreterContext = new
bookInterpreterContext.addTitleAndAuthor(
BookInterpreterContext();
new TitleAndAuthor("Crossfire", "James Marathon"));
bookInterpreterContext.addTitle("Pickwick Papers");
BookInterpreterClient bookInterpreterClient
bookInterpreterContext.addTitle("Great
Expectations"); = new
BookInterpreterClient(bookInterpreterContext);
bookInterpreterContext.addTitle("Wuthering Heights");
System.out.println("show author ->"
bookInterpreterContext.addTitle("Crossfile");
+ bookInterpreterClient.interpret("show author"));
bookInterpreterContext.addAuthor("William
Shakespeare"); System.out.println("show title ->"
bookInterpreterContext.addAuthor("Emily Bronte"); + bookInterpreterClient.interpret("show title"));
bookInterpreterContext.addAuthor("James Marathon"); System.out.println("show author for title <Crossfire>
->"
bookInterpreterContext.addTitleAndAuthor(
+ bookInterpreterClient.interpret("show author for
new TitleAndAuthor("Pickwick Papers", "William
title <Crossfire>"));
Shakespeare"));
System.out.println("show title for author <William
Shakespeare> ->"
+ bookInterpreterClient.interpret(
"show title for author <William Shakespeare>"));
System.out.println();
}
}
13 МАИ, каф 806, ППС
14. Паттерны проектирования
поведение объектов /
class BookInterpreterClient { if (currentToken.equals("title")) {
BookInterpreterContext bookInterpreterContext; if (mainQuery == ‘ ‘) {
public BookInterpreterClient(BookInterpreterContext mainQuery = ‘T’;
parm) {
} else {
bookInterpreterContext = parm;
if ((subQuery == ‘ ‘) && (forUsed)) {
}
subQuery = ‘T’;
public String interpret(String expression) {
}
StringTokenizer expressionTokens = new
}
StringTokenizer(expression);
}
String currentToken;
...
char mainQuery = ‘ ‘, subQuery = ‘ ‘;
String searchString = null;
boolean forUsed = false, searchStarted = false;
boolean searchEnded = false;
StringBuffer result = new StringBuffer();
while (expressionTokens.hasMoreTokens()) {
currentToken = expressionTokens.nextToken();
14 МАИ, каф 806, ППС
15. Паттерны проектирования
поведение объектов /
BookAbstractExpression abstractExpression; case ‘T’ : {
switch (mainQuery) { switch (subQuery) {
case ‘A’ : { case ‘A’ : {
switch (subQuery) { abstractExpression = new
BookTitleAuthorExpression(searchString);
case ‘T’ : {
break;
abstractExpression = new
BookAuthorTitleExpression(searchString); } default : {
break; abstractExpression = new
BookTitleExpression();
} default : {
break;
abstractExpression = new
BookAuthorExpression(); }
break; }
} break;
} } default : return result.toString();
break; }
}
result.append(abstractExpression.interpret(bookInterprete
rContext));
return result.toString();
}
}
15 МАИ, каф 806, ППС
16. Паттерны проектирования
поведение объектов /
class BookInterpreterContext { abstract class BookAbstractExpression {
private ArrayList titles = new ArrayList(); public abstract String interpret(BookInterpreterContext parm);
private ArrayList authors = new ArrayList(); }
private ArrayList titlesAndAuthors = new ArrayList(); class BookAuthorExpression extends BookAbstractExpression {
public void addTitle(String title) {titles.add(title);} public String interpret(BookInterpreterContext parm) {
public void addAuthor(String author) {authors.add(author);} ArrayList authors = parm.getAllAuthors();
public void addTitleAndAuthor(TitleAndAuthor titleAndAuthor) ListIterator authorsIterator = authors.listIterator();
{titlesAndAuthors.add(titleAndAuthor);} StringBuffer titleBuffer = new StringBuffer("");
public ArrayList getAllTitles() {return titles;} boolean first = true;
public ArrayList getAllAuthors() {return authors;} while (authorsIterator.hasNext()) {
public ArrayList getAuthorsForTitle(String titleIn) { if (!first) {titleBuffer.append(", ");}
ArrayList authorsForTitle = new ArrayList(); else {first = false;}
TitleAndAuthor tempTitleAndAuthor; titleBuffer.append((String)authorsIterator.next());
ListIterator titlesAndAuthorsIterator = titlesAndAuthors.listIterator(); }
while (titlesAndAuthorsIterator.hasNext()) { return titleBuffer.toString();
tempTitleAndAuthor = (TitleAndAuthor)titlesAndAuthorsIterator.next(); }
if (titleIn.equals(tempTitleAndAuthor.getTitle())) { }
authorsForTitle.add(tempTitleAndAuthor.getAuthor()); class BookAuthorTitleExpression extends BookAbstractExpression {
} String title;
} public BookAuthorTitleExpression(String parm) {title = parm;}
return authorsForTitle; public String interpret(BookInterpreterContext parm) {
} ArrayList authorsAndTitles = parm.getAuthorsForTitle(title);
public ArrayList getTitlesForAuthor(String authorIn) { ListIterator authorsAndTitlesIterator = authorsAndTitles.listIterator();
ArrayList titlesForAuthor = new ArrayList(); StringBuffer authorBuffer = new StringBuffer("");
TitleAndAuthor tempTitleAndAuthor; boolean first = true;
ListIterator authorsAndTitlesIterator = titlesAndAuthors.listIterator(); while (authorsAndTitlesIterator.hasNext()) {
while (authorsAndTitlesIterator.hasNext()) { if (!first) {authorBuffer.append(", ");}
tempTitleAndAuthor = (TitleAndAuthor)authorsAndTitlesIterator.next(); else {first = false;}
if (authorIn.equals(tempTitleAndAuthor.getAuthor())) { authorBuffer.append((String)authorsAndTitlesIterator.next());
titlesForAuthor.add(tempTitleAndAuthor.getTitle()); }
} return authorBuffer.toString();
} }
return titlesForAuthor; }
}
}
16 МАИ, каф 806, ППС
17. Паттерны проектирования
поведение объектов
Iterator
Описание задачи
Необходимо осуществить перебор
объектов в разнотипных коллекциях.
Описание решения
У коллекций создается единый
интерфейс для перебора.
Когда применять
Когда в переборах не важна структура
коллекции (индекс элементов и т.д.)
Пример
оператор foreach в C#
17 МАИ, каф 806, ППС
18. Паттерны проектирования
поведение объектов /
public class IteratorPattern { public interface CollectionIF {
public static void main(String[] args) { // Interface for creating a
String[] books = new String[8]; // collection that needs iterating.
books[0] = "PowerBuilder Developers Guide, 1994"; public IteratorIF iterator();
books[1] = "Informix Developers Guide, 1995"; public Collection elements();
books[2] = "Informix Universal Data Option, 1996"; }
books[3] = "SQL Server Developers Guide, 1999";
books[4] = "SilverStream Success I, 1999"; public class ConcreteCollection implements CollectionIF {
books[5] = "SilverStream Success II, 2000"; // Builds an iterable list of elements
books[6] = "J2EE Unleashed, 2001"; private List list = new ArrayList();
books[7] = "Enterprise Architect Study Guide, 2002"; public ConcreteCollection(Object[] objectList) {
CollectionIF collection = new for (int i=0; i < objectList.length; i++) {
ConcreteCollection(books);
list.add(objectList[i]);
IteratorIF iterator = collection.iterator();
}
int i = 0;
}
while (iterator.hasNext()) {
public IteratorIF iterator() {
System.out.println((++i)+" "+iterator.next());
return new ConcreteIterator(this);
}
}
}
public Collection elements() {
}
return Collections.unmodifiableList(list);
}
}
18 МАИ, каф 806, ППС
19. Паттерны проектирования
поведение объектов /
public class ConcreteIterator implements IteratorIF { public interface IteratorIF {
private List list; // Interface for Iterators.
private int index; public boolean hasNext();
public ConcreteIterator(CollectionIF parm) { public Object next();
list = (List) parm.elements(); }
index = 0;
}
public Object next() throws RuntimeException {
try {
return list.get(index++);
} catch (IndexOutOfBoundsException ioobe) {
throw new RuntimeException("No Such Element");
}
}
public boolean hasNext() {
return (index < list.size()) ? true : false;
}
}
19 МАИ, каф 806, ППС
20. Паттерны проектирования
поведение объектов
Mediator
Описание задачи
Необходимо контролировать
поведение группы объектов, при этом
избегая перекрестных ссылок между
ними.
Описание решения
Создается mediator в котором
описываются алгоритмы группового
поведения.
Когда применять
Можно явно отделить алгоритм
групповой работы объектов, от самих
объектов.
Пример
Пользовательский интерфейс (когда
значения в одних полях влияют на то
как выглядит вся форма).
20 МАИ, каф 806, ППС
22. Паттерны проектирования
поведение объектов /
public class MediatorPattern { public interface ColleagueIF { }
public static void main(String[] args) {
MediatorIF mediator = new ConcreteMediator(); public class ConcreteColleague1 implements ColleagueIF {
ColleagueIF colleague1 = new private MediatorIF mediator;
ConcreteColleague1(mediator);
// This colleague uses a boolean for it’s state.
ColleagueIF colleague2 = new
private boolean state;
ConcreteColleague2(mediator);
public ConcreteColleague1(MediatorIF parm) {
System.out.println("colleague1.toString()="+colleague
1); this.mediator = parm;
this.mediator.registerColleague1(this);
System.out.println("colleague2.toString()="+colleague
}
2);
public void setState(boolean parm) {
System.out.println("Calling
colleague1.changeState()"); this.state = parm;
((ConcreteColleague1) colleague1).changeState(); }
// Display colleague values now. public void changeState() {
System.out.println("colleague1.toString()="+colleague1); state = state ? false : true;
System.out.println("colleague2.toString()="+colleague2); mediator.state1Changed();
System.out.println("Calling colleague2.changeState()"); }
((ConcreteColleague2) colleague2).changeState(); public String toString() {
// Display colleague values now. return new Boolean(state).toString();
System.out.println("colleague1.toString()="+colleague1); }
System.out.println("colleague2.toString()="+colleague2); }
}
}
22 МАИ, каф 806, ППС
23. Паттерны проектирования
поведение объектов /
public class ConcreteColleague2 implements ColleagueIF { public class ConcreteMediator implements MediatorIF {
private MediatorIF mediator; ColleagueIF colleague1;
private String state = "false"; ColleagueIF colleague2;
public ConcreteColleague2(MediatorIF parm) { public void registerColleague1(ColleagueIF parm) {
this.mediator = parm; this.colleague1 = (ConcreteColleague1) parm;
this.mediator.registerColleague2(this); }
} public void registerColleague2(ColleagueIF parm) {
public void setState(String parm) { this.colleague2 = (ConcreteColleague2) parm;
this.state = parm; }
} public void state1Changed() {
public void changeState() { String s = (colleague2.toString().equals("true")) ?
"false" : "true";
state = state.equals("false") ? "true" : "false";
((ConcreteColleague2) colleague2).setState(s);
mediator.state2Changed();
}
}
public void state2Changed() {
public String toString() {
boolean b = (colleague1.toString().equals("true")) ?
return state;
false : true;
}
((ConcreteColleague1) colleague1).setState(b);
}
}
public interface MediatorIF {
}
public void registerColleague1(ColleagueIF parm);
public void registerColleague2(ColleagueIF parm);
public void state1Changed();
public void state2Changed();
}
23 МАИ, каф 806, ППС
24. Паттерны проектирования
поведение объектов
Memento
Описание задачи
Необходимо сохранять состояние
системы для отката.
Описание решения
Создается объект, сохраняющий
состояние. В критических точках в него
сохраняется состояние.
Когда применять
Состояние объекта не может быть
получено через публичные
интерфейсы (по причинам
инкапсуляции).
Пример
Реализация операции Undo в
пользовательском интерфейсе.
24 МАИ, каф 806, ППС
26. Паттерны проектирования
поведение объектов /
public class Caretaker { ;
public static void run() { public class Originator {
Originator originator = new Originator(); private boolean state;
originator.setState(true); private String name;
originator.setName("The Originator"); private String other;
// Create memento. public Memento createMemento() {
Memento memento = originator.createMemento(); return new Memento(state, name);
// Change originator values. }
originator.setState(false); public void recoverFromMemento(Memento memento) {
originator.setName("To be undone."); this.state = memento.getState();
originator.recoverFromMemento(memento); this.name = memento.getName();
System.out.println(originator); }
} public void setState(boolean parm) {
} this.state = parm;
}
public class Memento { public void setName(String parm) {
private boolean state; this.name = parm;
private String name; }
Memento(boolean parm1, String parm2) { public String toString() {
this.state = parm1; return "Originator.toString() state="+state+",
name="+name;
this.name = parm2;
}
}
}
boolean getState() {return this.state;}
String getName() {return this.name;}
}
26 МАИ, каф 806, ППС
27. Паттерны проектирования
поведение объектов
Observer
Описание задачи
При изменении состояния одного
объекта необходимо каскадно менять
состояние других объектов.
Описание решения
Объект хранит ссылок зависимых
объектов и нотифицирует их при
изменениях.
Когда применять
Когда необходимо нотифицировать
объекты не задумываясь об их природе
(однотипно).
Пример
Пользовательский интерфейс (при
изменении значения в поле
необходимо пересчитать другие поля).
27 МАИ, каф 806, ППС
29. Паттерны проектирования
поведение объектов /
public class ObserverPattern { public class ConcreteSubject implements SubjectIF {
public static void main(String[] args) { List observers = new ArrayList();
ObserverIF observer1 = new ConcreteObserver(); public void addObserver(ObserverIF parm)
{observers.add(parm);}
ObserverIF observer2 = new ConcreteObserver();
public void removeObserver(ObserverIF parm)
ConcreteSubject subject = new ConcreteSubject();
{observers.remove(observers.indexOf(parm));}
subject.addObserver(observer1);
public void notifyObservers() {
subject.addObserver(observer2);
for (Iterator i = observers.iterator(); i.hasNext();)
// Use loop to simulate time.
((ObserverIF) i.next()).update();}
for(int i=0;i < 10;i++) subject.doSomething();
public void doSomething() {notifyObservers();}
subject.removeObserver(observer1);
}
// Another loop to simulate time.
for(int i=0;i < 10;i++) {
public interface ObserverIF {
System.out.print(i+": ");
public void update();
subject.doSomething();
}
System.out.println();
}
public interface SubjectIF {
}
public void addObserver(ObserverIF parm);
}
public void removeObserver(ObserverIF parm);
public class ConcreteObserver implements ObserverIF {
public void notifyObservers();
private ConcreteSubject subject;
}
public void update() {
if (subject == null) { subject = new
ConcreteSubject(); }
}
}
29 МАИ, каф 806, ППС
30. Паттерны проектирования
поведение объектов
State
Описание задачи
Необходимо реализовать сложную
логику перехода состояний для
объекта (например, в событийно
ориентированной архитектуре).
Описание решения
Для каждого состояния создается класс
с функцией обработки событий.
Когда применять
Когда структура программы близка к
автоматной.
Пример
Организация сложного диалога с
пользователем в UI.
30 МАИ, каф 806, ППС
32. Паттерны проектирования
поведение объектов /
public class StatePattern { public class Context {
public static void main(String[] args) { // Initial state.
Context context = new Context(); private StateIF state = new ConcreteState1();
context.request(); // Request operation.
context.changeState(); public void request() {
// call request. state.handle();
context.request(); }
System.out.println(); // Switch states
} public void changeState() {
} if (state instanceof ConcreteState1)
public class ConcreteState1 implements StateIF { state = new ConcreteState2();
public void handle() { else
System.out.println("ConcreteState1.handle() state = new ConcreteState1();
called.");
}
}
}
}
public class ConcreteState2 implements StateIF {
public interface StateIF {
public void handle() {
public void handle();
System.out.println("ConcreteState2.handle()
}
called.");
}
}
32 МАИ, каф 806, ППС
33. Паттерны проектирования
поведение объектов
Strategy
Описание задачи
Необходимо иметь несколько схожих
алгоритмов для решения одной задачи.
Описание решения
У алгоритмов выделяется общий
интерфейс и общий контекст с
данными.
Когда применять
Алгоритмы могут иметь одинаковый
интерфейс и алгоритм должен
выбираться динамически.
Пример
Получение текста из структур в разном
формате (plain-text, html, xml).
33 МАИ, каф 806, ППС
34. Паттерны проектирования
поведение объектов /
public class StrategyPattern { public class Context {
public static void main(String[] args) { // Reference to the strategy.
StrategyIF strategy1 = new ConcreteStrategy1(); StrategyIF strategy;
StrategyIF strategy2 = new ConcreteStrategy2(); // Register reference to strategy on construction.
Context context1 = new Context(strategy1); public Context(StrategyIF parm) {this.strategy = parm;}
Context context2 = new Context(strategy2); // Call strategy’s method.
context1.contextInterface("J2EE Unleashed"); public void contextInterface(String parm)
{strategy.algorithmInterface(parm);}
context2.contextInterface("J2EE Unleashed");
}
context1.contextInterface("The Secret Commissions");
context2.contextInterface("The Secret Commissions");
public interface StrategyIF {
System.out.println();
public void algorithmInterface(String parm);
}
}
}
public class ConcreteStrategy1 implements StrategyIF {
public void algorithmInterface(String parm) {
System.out.println(parm.toUpperCase());
}
}
public class ConcreteStrategy2 implements StrategyIF {
public void algorithmInterface(String parm) {
System.out.println((parm.toLowerCase().startsWith("the
")) ? parm.substring(4) + ", " + parm.substring(0,4)
: parm);
}
}
34 МАИ, каф 806, ППС
35. Паттерны проектирования
поведение объектов
Template Method
Описание задачи
Существует алгоритм, который состоит
из набора атомарных задач.
Описание решения
Алгоритм описывается в
TemplateMethod, атомарные части
описываются в методах, которые могут
переопределяться.
Когда применять
Когда общий алгоритм не меняется
(есть возможность выделить общую
часть).
Пример
Сохранение информации в разные
форматы файлов.
35 МАИ, каф 806, ППС
36. Паттерны проектирования
поведение объектов /
public class TemplateMethodPattern { public class ConcreteClass1 extends AbstractClass {
public static void main(String[] args) { public void primitiveOperation1() {
AbstractClass class1 = new ConcreteClass1();
System.out.println("ConcreteClass1.primitiveOperation1()
AbstractClass class2 = new ConcreteClass2();
called.");
class1.templateMethod();
}
class2.templateMethod();
public void primitiveOperationN() {
System.out.println();
} System.out.println("ConcreteClass1.primitiveOperationN()
called.");
}
}
public abstract class AbstractClass {
}
public void templateMethod() {
primitiveOperation1();
public class ConcreteClass2 extends AbstractClass {
primitiveOperationN();
public void primitiveOperation1() {
}
public abstract void primitiveOperation1();
System.out.println("ConcreteClass2.primitiveOperation1()
public abstract void primitiveOperationN(); called.");
} }
public void primitiveOperationN() {
System.out.println("ConcreteClass2.primitiveOperationN()
called.");
}
}
36 МАИ, каф 806, ППС
37. Паттерны проектирования
поведение объектов / visitor
Visitor
Описание задачи
Есть сложная структура объектов,
необходимо со всеми элементами
проделать операции (отличающиеся
для разных типов элементов).
Описание решения
Создается иерархия объектов с
алгоритмами (Visitor). В элементах
создается метод, который реализует
вызов алгоритма для конкретного типа
элемента.
Когда применять
Операция зависит от типа элемента.
Пример
Анализ динамических структур данных.
Разные анализаторы реализуют
проверку различных правил.
37 МАИ, каф 806, ППС
38. Паттерны проектирования
поведение объектов / visitor
Когда применять?
в структуре присутствуют объекты многих классов с различными интерфейсами и вы
хотите выполнять над ними операции, зависящие от конкретных классов;
над объектами, входящими в состав структуры, надо выполнять разнообразные, не
связанные между собой операции и вы не хотите ≪засорять≫ классы такими
операциями. Посетитель позволяет объединить родственные операции, поместив их в
один класс.
классы, устанавливающие структуру объектов, изменяются редко, но новые операции над
этой структурой добавляются часто. При изменении классов, представленных в структуре,
нужно будет переопределить интерфейсы всех посетителей, а это может вызвать
затруднения. Поэтому если классы меняются достаточно часто, то лучше определить
операции прямо в них.
38 МАИ, каф 806, ППС
40. Паттерны проектирования
поведение объектов /
public class VisitorPattern { public class ConcreteVisitor implements VisitorIF {
public static void main(String[] args) { public void visitConcreteElementA(ConcreteElementA
parm) { parm.operationA();}
ElementIF[] elements = new ElementIF[2];
public void visitConcreteElementB(ConcreteElementB
elements[0] = new ConcreteElementA();
parm) { parm.operationB();}
elements[1] = new ConcreteElementB();
}
ObjectStructure objectStructure = new
ObjectStructure(elements); public interface ElementIF {
objectStructure.visitElements();
public void accept(VisitorIF parm);}
}
}
public class ObjectStructure {
public class ConcreteElementA implements ElementIF {
private List objectStruct;
public void accept(VisitorIF parm) {
private VisitorIF visitor;
parm.visitConcreteElementA(this); }
public ObjectStructure(ElementIF[] parm) {
public void operationA() {
objectStruct = Arrays.asList(parm);}
System.out.println("ConcreteElementA.operationA()
public void visitElements() {
called."); }}
if (visitor == null) { visitor = new
public class ConcreteElementB implements ElementIF {
ConcreteVisitor(); }
public void accept(VisitorIF parm) {
for (Iterator i = objectStruct.iterator();
parm.visitConcreteElementB(this);} i.hasNext();) {
public void operationB() { ((ElementIF) i.next()).accept(visitor);} }
System.out.println("ConcreteElementB.operationB() }
called.");}}
public interface VisitorIF {
public void visitConcreteElementA(ConcreteElementA parm);
public void visitConcreteElementB(ConcreteElementB parm);
}
40 МАИ, каф 806, ППС
41. Пример. Приложение ControlPanel
class Pattern Example
Draw Context
Next Element
1
0..1
UIForm «interface» Flyweight
ControlPanelItem
1 1..* + Draw(DrawContext) : void
+ Execute() : void Command
+ HandleMouseEvent(int) : void
+ Load() : ControlPanelItem
Chain of
Responsobility
ItemAddHardw are ItemAddSoftw are ItemSystem
Builder
Director
result[0] = ItemAddHardware.Load();
+ Construct() : ControlPanelItem[] result[1] = ItemAddSoftware.Load();
result[2] = ItemSystem.Load();
41 МАИ, каф 806, ППС
42. Enterprise Library
Data Access Application Block
Паттерн помогает работать с
разными типами и
экземплярами баз данных.
42 МАИ, каф 806, ППС
43. Enterprise Library
Logging Application Block
Паттерн помогает настраивать различные
уровни логирования, осуществлять
логгирование в различные места (event-log,
база данных, e-mail, msmq)
43 МАИ, каф 806, ППС
44. Enterprise Library
Caching Application Block
Паттерн решает задачи кеширования данных в
приложении, включая их долговременное
хранение (например, в базе данных).
44 МАИ, каф 806, ППС