Группа 10 назначена на курс Алгебра 4 страница
State(Состояние) – позволяет объекту изменять свое поведение за счет изменения внутреннего объекта состояния;
Strategy (Стратегия) – задает набор алгоритмов с возможностью выбора одного из классов для выполнения конкретной задачи во время создания объекта;
Template Method(Шаблонный Метод) – создает родительский класс, использующий несколько методов, реализация которых возложена на производные классы;
Visitor(Посетитель) – представляет операцию в одном или нескольких связанных классах некоторой структуры, которую вызывает специфичный для каждого такого класса метод в другом классе.
Шаблон Command
Необходимо создать объект-команду, метод которого может быть вызван, а сам объект может быть сохранен и передан в качестве параметра метода или возвращен как любой другой объект. Инкапсулирует запрос как объект.
Объект-источник запроса отделяется от команды, но от его типа зависит, какая из команд будет выполнена.
Рис. 5.11. Пример реализации шаблона Command
/*пример # 27 : описание команды и конкретные реализации : Command.java : AddCommand.java : MultCommand.java */
package chapt05.command;
public abstract class Command {
public abstract void execute();
}
package chapt05.command;
import chapt05.receiver.*;
public class MultCommand extends Command {
private ArrayOperation ao;
public MultCommand (ArrayOperation ao) {
this.ao = ao;
}
public void execute () {
this.ao.product();
}
}
package chapt05.command;
import chapt05.receiver.*;
public class AddCommand extends Command {
private ArrayOperation ao;
public AddCommand (ArrayOperation ao) {
this.ao = ao;
}
public void execute() {
this.ao.sum();
}
}
/*пример # 28 : класс Receiver (получатель) - располагает информацией о способах выполнения операций : ArrayOperation.java */
package chapt05.receiver;
public class ArrayOperation {
private int[] mass;
public ArrayOperation(int[] mass) {
this.mass = mass;
}
public void sum() {
int sum = 0;
for (int i : mass)
sum += i;
System.out.println(sum);
}
public void product() {
int mult = 1;
for (int i : mass)
mult *= i;
System.out.println(mult);
}
}
/*пример # 29 : класс Invoker (инициатор)-обращается к команде для выполнения запроса : ManagerCommands.java */
package chapt05.invoker;
import chapt05.command.*;
public class ManagerCommands {
private Command command;
public ManagerCommands(Command command) {
this.command = command;
}
public void setManager(Command command) {
this.command = command;
}
public void exec() {
command.execute();
}
}
/*пример # 30 : простое использование шаблона Command : Main.java */
package chapt05;
import chapt05.invoker.*;
import chapt05.receiver.*;
import chapt05.command.*;
public class Main {
public static void main(String[] args) {
int mass[] = {-1, 71, 45, -20, 48, 60, 19};
/*класс получатель(Receiver)-располагают информацией о способах
выполнения операций*/
ArrayOperation receiver = new ArrayOperation (mass);
//инициализация команды
Command operation1 = new MultCommand(receiver);
Command operation2 = new AddCommand(receiver);
//класс инициатор (Invoker)-обращается к команде для выполнения запроса
ManagerCommands manager = new ManagerCommands(operation1);
manager.exec();
manager.setManager(operation2);
manager.exec();
}
}
Объект-команда получен прямой инициализацией на основе переданного параметра. На практике данный объект создается или извлекается из коллекции на основе признака вызываемой команды. Объект ManagerCommands инициализируется командой и обладает простым интерфейсом для выполнения специализируемой задачи. В этом случае появляется возможность изменять реакцию приложения на запрос команды простой заменой объекта-управления.
Шаблон Strategy
Необходимо определить семейство алгоритмов, инкапсулировать каждый из них и сделать их взаимозаменяемыми. Стратегия позволяет изменять алгоритмы независимо от клиентов, которые ими пользуются.
Рис. 5.12. Пример реализации шаблона Strategy
Класс Operation объявляет общий для всех поддерживаемых алгоритмов интерфейс, которым пользуется класс Sorting для вызова конкретного алгоритма, определенного в классе SortByMax или SortByMin. Класс Sorting конфигурируется объектом класса SortByXxx, объявляет ссылку на объект класса Operation и может определять интерфейс, позволяющий объекту Operation получить доступ к информации, в данном случае для сортировки массива.
Использование шаблона позволяет отказаться от условных операторов при выборе нужного поведения. Стратегии могут предлагать различные реализации одного и того же поведения. Класс-клиент вправе выбирать подходящую стратегию в зависимости от своих требований.
/*пример # 31 : общий интерфейс и классы конкретных стратегий :
Operation.java : SortByMax.java : SortByMin.java */
package chapt05.strategy;
public abstract classOperation {
public abstract void sort(int mass[]);
}
package chapt05.strategy;
public class SortByMax extends Operation {
public void sort(int mass[]) {
for (int i = 0; i < mass.length; ++i) { for (int j = i; j < mass.length; ++j) {
if(mass[j] > mass[i]){
int m = mass[i];
mass[i] = mass[j];
mass[j] = m;
}
}
}
System.out.print("SortByMax : ");
for (int i : mass)
System.out.print(i + " ");
System.out.println('\n'); }
}
package chapt05.strategy;
public class SortByMin extends Operation {
public void sort(int mass[]) {
for (int i = 0; i < mass.length; ++i) { for (int j = i; j < mass.length; ++j) {
if (mass[j] < mass[i]){
int m = mass[i];
mass[i] = mass[j];
mass[j] = m;
}
}
}
System.out.print("SortByMin : ");
for (int i : mass)
System.out.print(i + " ");
System.out.println('\n');}
}
/*пример # 32 : класс выбора стратегии : Sorting.java */
package chapt05.strategy;
public class Sorting {
private Operation operation = null;
public Sorting(int operation){
switch(operation) {
case 1: this.operation = new SortByMax();
break;
case 2: this.operation = new SortByMin();
break;
default: System.out.println(
"Такая операция отсутствует"); }
}
public void sorting(int[] mass) {
if (operation != null) operation.sort(mass);
else return;
}
}
/*пример # 33 : использование шаблона Strategy: Main.java */
package chapt05.strategy;
public class Main {
public static void main(String args[]) {
int mass[] = {28, 9, 71, 8, 35, 5, 51};
Sorting cont1 = new Sorting(1);
Sorting cont2 = new Sorting(2);
cont1.sorting(mass);
cont2.sorting(mass);
}
}
Шаблон Observer
Требуется определить связь «один ко многим» между объектами таким образом, чтобы при изменении состояния одного объекта все связанные с ним объекты оповещались об этом и автоматически изменяли свое состояние. В языке Java этот шаблон используется под названием Listener.
Рис. 5.13. Пример реализации шаблона Observer
Класс Rectangle(субъект) располагает информацией о своих наблюдателях и предоставляет интерфейс для регистрации и уведомления наблюдателей. Класс OperationObserver(наблюдатель) определяет интерфейс обновления для объектов, которые должны быть уведомлены об изменении субъекта. Класс Perimeter (конкретный наблюдатель) хранит или получает ссылку на объект класса Rectangle, сохраняет данные и реализует интерфейс обновления, определенный в классе OperationObserver для поддержки согласованности с субъектом.
Шаблон обеспечивает автоматическое уведомление всех подписавшихся на него объектов. Кроме этого, применение шаблона Observer абстрагирует связь субъекта и наблюдателя. Субъект имеет информацию только о том, что у него есть некоторое число наблюдателей, каждый из которых подчиняется интерфейсу абстрактного класса-наблюдателя.
/*пример # 34 : класс-субъект, за которым следят все классы-наблюдатели :
Rectangle.java */
package chapt05.observer;
import java.util.*;
public class Rectangle {
private float width;
private float height;
private ArrayList<OperationObserver> observerList =
new ArrayList<OperationObserver>();
public Rectangle(float width, float height) {
this.width = width;
this.height = height;
}
public void addObserver(OperationObserver observer) {
observerList.add(observer);
}
public float getWidth() {
return width;
}
public float getHeight() {
return height;
}
public void setWidth(float width) {
this.width = width;
notifyObservers();
}
public void setHeight(float height) {
this.height = height;
notifyObservers();
}
private void notifyObservers() {
Iterator it = observerList.iterator();
while (it.hasNext()) {
((OperationObserver) it.next()).valueChanged(this);
}
}
public String toString() {
String s = "";
Iterator it = observerList.iterator();
while (it.hasNext()) {
s = s +
((OperationObserver) it.next()).toString() + '\n';
}
return s;
}
}
Классы Perimeter и Square наследуются от абстрактного класса
OperationObserver и являются наблюдателями. Как только субъект
Rectangle изменяется, состояние этих объектов также подвергается изменению в соответствии с реализованным интерфейсом.
/*пример # 35 : классы-наблюдатели : OperationObserver.java : Square.java :
Perimeter.java */
package chapt05.observer;
public abstract class OperationObserver {
public abstract float valueChanged(Rectangle observed);
}
package chapt05.observer;
public class Perimeter extends OperationObserver {
private float perimeter;
public float valueChanged(Rectangle observed) {
return perimeter =
2 * (observed.getWidth() + observed.getHeight());
}
public String toString() {
return "P = " + perimeter;
}
}
package chapt05.observer;
public class Square extends OperationObserver {
private float square;
public float valueChanged(Rectangle observed) {
return square =
observed.getWidth() * observed.getHeight();
}
public String toString() {
return "S = " + square;
}
}
/*пример # 36 : использование шаблона Observer : Main.java */
package chapt05.observer;
public class Main {
public static void main(String args[]) {
Rectangle observed = new Rectangle(5, 3);
System.out.println(observed.toString());
observed.addObserver(new Square());
observed.addObserver(new Perimeter());
observed.setWidth(10);
System.out.println(observed.toString());
observed.setHeight(8);
System.out.println(observed.toString());
}
}