|
|||||||
АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
Default : throw newEnumConstantNotPresentException(Signs. class, sign.name()); } } }
Рис. 5.7. Пример реализации шаблона AbstractFactory Производители объектов реализуют методы по созданию не связанных иерархическими зависимостями объектов. Класс BaseFactory – абстрактная фабрика, а классы BlackFactory и WhiteFactory конкретные производители объектов, наследуемые от нее. Конкретные фабрики могут создавать черные или белые объекты-продукты. /*пример # 12: классы-фабрики по созданию несвязанных объектов: BaseFactory.java: BlackFactory.java: WhiteFactory.java */ package chapt05.abstractfactory; public abstract class BaseFactory { public abstract Circle createCircle(double radius); public abstract Triangle createTriangle(double a, double b); } package chapt05.abstractfactory; public class BlackFactory extends BaseFactory { public Circle createCircle(double radius) { return new BlackCircle(radius); } public Triangle createTriangle(double a, double b){ return new BlackTriangle(a,b); } } package chapt05.abstractfactory; public class WhiteFactory extends BaseFactory { public Circle createCircle(double radius) { return new WhiteCircle(radius); } public Triangle createTriangle(double a, double b){ return new WhiteTriangle(a, b); } } Рассматриваются два вида классов-продуктов: Circle, Triangle. Каждый из них может быть представлен в одном из двух цветов: белом или /*пример # 13: классы-продукты: Circle.java: Triangle.java */ package chapt05.abstractfactory; public abstract class Circle { protected double radius; protected String color; public abstract void square(); } package chapt05.abstractfactory; public class BlackCircle extends Circle { public BlackCircle(double radius){ this. radius = radius; color = "Black"; } public void square(){ double s = Math.PI * Math.pow(radius, 2); System. out. println(color + " Circle" + " Square = " + s); } } package chapt05.abstractfactory; public class WhiteCircle extends Circle{ public WhiteCircle(double radius){ this. radius = radius; color = "White"; } public void square(){ double s = Math.PI * Math.pow(radius, 2); System. out. println(color + " Circle " + "Square = " + s); } } package chapt05.abstractfactory; public abstract class Triangle { protected double a, b; protected String color; public abstract void square(); } package chapt05.abstractfactory; public class BlackTriangle extends Triangle { public BlackTriangle (double a, double b){ this. a = a; this. b = b; color = "Black"; } public void square(){ double s = a * b / 2; System. out. println(color + " Triangle" + " Square = " + s); } } package chapt05.abstractfactory; public class WhiteTriangle extends Triangle { public WhiteTriangle (double a, double b) { this. a = a; this. b = b; color = "White"; } public void square(){ double s = 0.5 * a * b; System. out. println(color + " Triangle" + " Square = " + s); } } Ниже будут созданы объекты всех классов и всех цветов. /*пример # 14: демонстрация работы шаблона AbstractFactory: Main.java */ package chapt05.abstractfactory; public class Main { public static void main(String[] args) { BaseFactory factory1 = AbstractFactory. getFactory ("black"); BaseFactory factory2 = AbstractFactory. getFactory ("white"); Circle ob1 = factory1.createCircle(1.232); Circle ob2 = factory2.createCircle(1); Triangle ob3 = factory1.createTriangle(12,5); Triangle ob4 = factory2.createTriangle(1,7);
ob1.square(); ob2.square(); ob3.square(); ob4.square(); } } Шаблон Builder Необходимо задать конструирование сложного объекта, определяя для него только тип и содержимое. Детали построения объекта остаются скрытыми.
Рис. 5.8. Пример реализации шаблона Builder Класс BaseBuilder определяет абстрактный интерфейс для создания частей объекта сложного класса User. Классы XMLBuilder и DBBuilder конструируют и собирают вместе части объекта класса User, а также представляет внешний интерфейс для доступа к нему. В результате объекты-строители могут работать с разными источниками, определяющими содержимое, не требуя при этом никаких изменений. При использовании этого шаблона появляется возможность контролировать пошагово весь процесс создания объекта-продукта. Простая реализация шаблона Builder приведена ниже. /*пример # 15: «сложный» для построения объект: User.java */ package chapt05.builder; public class User { private String login = "Guest"; private String password = "Kc";
public String getLogin() { return login; } public void setLogin(String login) { this. login = login; } public String getPassword() { return password; } public void setPassword(String password) { this. password = password; } } Класс BaseBuilder – абстрактный класс-строитель, объявляющий в качестве поля ссылку на создаваемый объект и абстрактные методы его построения. Классы XMLBuilder и DBBuilder – наследуемые от него классы, реализующие специальные способы создания объекта. Таким образом, используя один класс User можно создать или администратора или модератора. /*пример # 16: разные способы построения объекта: BaseBuilder.java: XMLBuilder.java: DBBuilder.java */ package chapt05.builder; public abstract class BaseBuilder { protected User user = new User();
public User getUser() { return user; } public abstract void buildLogin(); public abstract void buildPassword(); } package chapt05.builder; public class XMLBuilder extends BaseBuilder {
public void buildLogin() { //реализация user.setLogin("Admin"); } public void buildPassword() { //реализация user.setPassword("Qu"); } } package chapt05.builder; public class DBBuilder extends BaseBuilder {
public void buildLogin() { //реализация user.setLogin("Moderator"); } public void buildPassword() { //реализация user.setPassword("Ku"); } } Процесс создания объектов с использованием одного принципа реализован ниже. /*пример # 17: тестирование процесса создания объекта: Main.java */ package chapt05.builder; public class Main { private static User buildUser(BaseBuilder builder) { builder.buildLogin(); builder.buildPassword(); return builder.getUser(); } public static void main(String args[]) { User e1 = buildUser (new XMLBuilder()); User e2 = buildUser (new DBBuilder());
System. out. println(e1.getLogin()); System. out. println(e1.getPassword()); System. out. println(e2.getLogin()); System. out. println(e2.getPassword()); } } Шаблон Singleton Необходимо создать объект класса таким образом, чтобы гарантировать невозможность инициализации другого объекта того же класса. Обычно сам класс контролирует наличие единственного экземпляра и он же предоставляет при необходимости к нему доступ. /*пример # 18: реализация шаблона «Одиночка»: Singleton.java */ package chapt05.singleton; public class Singleton {
private static Singleton instance = null; private SingletonTrust() { } public static Singleton getInstance() { if (instance == null) { System. out. println("Creating Singleton"); instance = new Singleton(); } return instance; } } Класс объявляет метод getInstance(), который позволяет клиентам получать контролируемый доступ к единственному экземпляру. Этот шаблон позволяет уточнять методы через подклассы, а также разрешить появление более чем одного экземпляра. Структурные шаблоны Структурные шаблоны отвечают за композицию объектов и классов. К структурным шаблонам относятся: Proxy (Заместитель) – подменяет сложный объект более простым и осуществляет контроль доступа к нему; Composite (Компоновщик) – группирует объекты в иерархические структуры и позволяет работать с единичным объектом так же, как с группой объектов; Adapter (Адаптер) – применяется при необходимости использовать вместе несвязанные классы. Поведение адаптируемого класса при этом изменяется на необходимое; Bridge (Мост) – разделяет представление класса и его реализацию, позволяя независимо изменять то и другое; Decorator (Декоратор) – представляет способ изменения поведения объекта без создания подклассов. Позволяет использовать поведение одного объекта в другом; Facade (Фасад) – создает класс с общим интерфейсом высокого уровня к некоторому числу интерфейсов в подсистеме. Шаблон Bridge Необходимо отделить абстракцию (Abstraction) от ее реализации (Implementor) так, чтобы и то и другое можно было изменять независимо. Шаблон Bridge используется в тех случаях, когда существует иерархия абстракций и соответствующая иерархия реализаций. Причем не обязательно точное соответствие между абстракциями и реализациями. Обычно абстракция определяет операции более высокого уровня, чем реализация.
Рис. 5.9. Пример реализации шаблона Bridge /*пример # 18: Implementor и его подкласс: Color.java: YellowColor.java */ package chapt05.implementor; public abstract class Color { //implementor public abstract void useBrush(); } package chapt05.implementor; public class YellowColor extends Color { public void useBrush() { System. out. println("BrushColor - Yellow"); } } Класс Color – абстрактный, реализующий Implementor. Класс /*пример # 19: абстракция и ее уточнения: Shape.java: Circle.java: Rectangle.java */ package chapt05.abstraction; import chapt05.implementor.*; public abstract class Shape { //abstraction protected Color color;
public Shape (){ color = null; } public Color getColor() { return color; } public void setColor(Color color) { this. color = color; } public abstract void performWithColor(); } package chapt05.abstraction; import chapt05.implementor.*; public class Circle extends Shape { public Circle(Color color) { setColor(color); } public void performWithColor() { System. out. println("Performing in Circle class"); color.useBrush(); } } package chapt05.abstraction; import chapt05.implementor.*; public class Rectangle extends Shape { public Rectangle(Color color) { setColor(color); } public void performWithColor() { System. out. println("Performing in Rectangle class"); color.useBrush(); } } Класс Shape – абстракция, классы Circle и Rectangle – уточненные абстракции. /*пример # 20: использование шаблона Bridge: Main.java */ package chapt05.bridge; import chapt05.abstraction.*; import chapt05.implementor.*; public class Main { public static void main(String args[]) { YellowColor color = new YellowColor(); new Rectangle(color).performWithColor(); new Circle(color).performWithColor(); } } Реализация больше не имеет постоянной привязки к интерфейсу. Реализацию абстракции можно динамически изменять и конфигурировать во время выполнения. Иерархии классов Abstraction и Implementor независимы и поэтому могут иметь любое число подклассов. Шаблон Decorator Необходимо расширить функциональные возможности объекта, используя прозрачный для клиента способ. Расширяемый класс реализует тот же самый интерфейс, что и исходный класс, делегируя исходному классу выполнение базовых операций. Шаблон Decorator даёт возможность динамического изменения поведения объектов в процессе выполнения приложения. Рис. 5.10. Пример реализации шаблона Decorator /*пример # 21: определение интерфейса для компонентов: Driver.java */ package chapt05.decorator; public abstract class Driver { public abstract void do(); } Класс DriverDecorator определяет для набора декораторов интерфейс, соответствующий интерфейсу класса Driver, и создает необходимые ссылки. /*пример # 22: интерфейс-декоратор для класса Driver: DriverDecorator.java */ package chapt05.decorator; public abstract class DriverDecorator extends Driver { protected Driver driver;
public DriverDecorator(Driver driver) { this. driver = driver; } public void do() { driver.do(); } } Класс CarDriver определяет класс, функциональность которого будет расширена. /*пример # 23: класс просто водителя: CarDriver.java */ package chapt05.decorator; public class CarDriver extends Driver { public void do() { //базовая операция System. out. println("I am a driver"); } } Класс BusDriver добавляет дополнительную функциональность /*пример # 24: класс водителя автобуса: BusDriver.java */ package chapt05.decorator; public class BusDriver extends DriverDecorator {
public BusDriver(Driver driver) { super (driver); } private void addedBehaviorOne() { System. out. println("I am bus driver"); } public void do() { driver.do(); addedBehaviorOne(); } } Класс CarDriverAndForwardingAgent добавляет дополнительную функциональность addedBehaviorTwo() необходимую для водителя-экспедитора, используя функциональность do() класса CarDriver. /*пример # 25: класс водителя-экспедитора:CarDriverAndForwardingAgent.java*/ package chapt05.decorator; public class CarDriverAndForwardingAgent extends DriverDecorator {
public CarDriverAndForwardingAgent(Driver driver){ super (driver); } private void addedBehaviorTwo() { System. out. println("I am a Forwarding Agent"); } public void do() { driver.do(); addedBehaviorTwo(); } } Создав экземпляр класса CarDriver можно делегировать ему выполнение задач, связанных с водителем автобуса или водителя-экспедитора, без написания специализированных полновесных классов. /*пример # 26: использование шаблона Decorator: Main.java */ package chapt05.decorator; public class Main { public static void main(String args[]){ Driver carDriver = new CarDriver(); Main runner = new Main(); runner.doDrive(carDriver);
runner.doDrive(new BusDriver(carDriver)); runner.doDrive( new CarDriverAndForwardingAgent(carDriver)); } public void doDrive(Driver driver){ driver.do(); } } Шаблоны поведения Шаблоны поведения характеризуют способы взаимодействия классов или объектов между собой. К шаблонам поведения относятся: Chain of Responsibility (Цепочка Обязанностей) – организует независимую от объекта-отправителя цепочку не знающих возможностей друг друга объектов-получателей, которые передают запрос друг другу; Command (Команда) – используется для определения по некоторому признаку конкретного класса, которому будет передан запрос для обработки; Iterator (Итератор) – позволяет последовательно обойти все элементы коллекции или другого составного объекта, не зная деталей внутреннего представления данных; Mediator (Посредник) – позволяет снизить число связей между классами при большом их количестве, выделяя один класс, знающий все о методах других классов; Memento (Хранитель) – сохраняет текущее состояние объекта для дальнейшего восстановления; Observer (Наблюдатель) – позволяет при зависимости между объектами типа «один ко многим» отслеживать изменения объекта; 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 class Operation { 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 наследуются от абстрактного класса /*пример # 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()); } } Поиск по сайту: |
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.111 сек.) |