Разделы презентаций


Паттерн Декоратор

Содержание

СодержаниеДекораторПримеры

Слайды и текст этой презентации

Слайд 1Паттерн Декоратор
Паттерн Декоратор: Добавляет дополнительные возможности к объекту динамически.

Декораторы предоставляют гибкую альтернативу наследованию для расширения функциональности.* *Исходное определение, данное

в книге «Паттерны проектирования» GoF (Addison Wesley, 1994).
Паттерн Декоратор  Паттерн Декоратор: Добавляет дополнительные возможности к объекту динамически. Декораторы предоставляют гибкую альтернативу наследованию для

Слайд 2Содержание
Декоратор
Примеры

СодержаниеДекораторПримеры

Слайд 3Суть паттерна
Декоратор
это структурный паттерн проектирования, который позволяет динамически добавлять

объектам новую функциональность, оборачивая их в полезные «обёртки».
Проблема
Вам нужно динамически

добавлять и снимать с объекта новые обязанности таким образом, чтобы он оставался совместим с остальным кодом программы.
Наследование — первое что приходит в голову, если вам нужно добавить новое поведение объекту. Но механизм наследования статичен — в программу нельзя на лету добавлять подклассы.
Решение
Декоратор имеет ещё одно название — Обёртка. Оно удачнее описывает суть паттерна. Итак, с Декоратором вы помещаете целевой объект в другой объект-обёртку, который расширяет базовое поведение объекта.
Оба объекта имеют общий интерфейс, поэтому пользователю всё равно с чем работать — с чистым объектом или обёрнутым.
Вы можете использовать несколько разных обёрток одновременно — результат будет иметь функции всех обёрток сразу.

Суть паттерна Декоратор это структурный паттерн проектирования, который позволяет динамически добавлять объектам новую функциональность, оборачивая их в

Слайд 4Структура
Компонент задаёт общий интерфейс обёрток и оборачиваемых объектов.
Конкретный Компонент определяет

класс оборачиваемых объектов. Он содержит какое-то базовое поведение, которое потом

изменяют декораторы.
Базовый Декоратор хранит ссылку на объект-компонент, им может быть как Конкретный компонент, так и один из Конкретных декораторов. Декоратор делегирует все свои операции вложенному объекту. Дополнительное поведение содержится в Конкретных декораторах.
Конкретные Декораторы — это различные вариации декораторов, которые содержат добавочное поведение. Оно выполняется до или после вызова аналогичного поведения обёрнутого объекта.

Структура Компонент задаёт общий интерфейс обёрток и оборачиваемых объектов.Конкретный Компонент определяет класс оборачиваемых объектов. Он содержит какое-то

Слайд 5Применимость
 Паттерн можно часто встретить в Java-коде, особенно в коде, работающем

с потоками данных.
Примеры Декораторов в стандартных библиотеках Java:
Все подклассы java.io.InputStream, OutputStream, Reader и Writer имеют конструктор,

принимающий объекты этих же классов.

java.util.Collections, методы checkedXXX(), synchronizedXXX() и unmodifiableXXX().
javax.servlet.http.HttpServletRequestWrapper и HttpServletResponseWrapper

Признаки применения паттерна: 
Декоратор можно распознать по создающим методам, которые принимают в параметрах объекты того же абстрактного типа или интерфейса, что и текущий класс.
Когда вам нужно добавлять обязанности объектам на лету, незаметно для кода, который их использует.
 Объекты помещают в обёртки, имеющие дополнительные поведения.
Обёртки и сами объекты имеют одинаковый интерфейс, а значит для клиентов нет разницы с чем работать — обычным или обёрнутым объектом.
 Когда нельзя расширить обязанности объекта с помощью наследования.
 Во многих языках программирования есть ключевое слово final, которое может заблокировать наследование класса.
Расширить такие классы можно только с помощью Декоратора.


Применимость Паттерн можно часто встретить в Java-коде, особенно в коде, работающем с потоками данных.Примеры Декораторов в стандартных библиотеках

Слайд 6Пример: Шифрование и сжатие данных
Пример показывает, как можно добавить новую

функциональность объекту, не меняя его класса.
Сначала класс бизнес-логики мог только

считывать и записывать данные напрямую. Применив паттерн Декоратор, мы получаем небольшие классы-обёртки, которые добавляют новые поведения до или после основной работы вложенного объекта.
Первая обёртка шифрует и расшифрует данные, а вторая — сжимает и распаковывает их.
Мы можем использовать обёртки как отдельно друг от друга, так и все вместе, обернув один декоратор другим.

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

Слайд 7Интерфейс, задающий базовые операции чтения и записи данных
package decorator.example.decorators;
public

interface DataSource {
void writeData(String data);
String readData(); }

Интерфейс, задающий базовые операции чтения и записи данныхpackage decorator.example.decorators; public interface DataSource { void writeData(String data); String

Слайд 8Класс, реализующий прямое чтение и запись данных
package decorator.example.decorators;
import java.io.*;

public class FileDataSource implements DataSource {
private String name;
public

FileDataSource(String name) {
this.name = name; }
@Override
public void writeData(String data) {
File file = new File(name);
try (OutputStream fos = new FileOutputStream(file)) {
fos.write(data.getBytes(), 0, data.length()); }
catch (IOException ex) { System.out.println(ex.getMessage()); } }
@Override
public String readData() {
char[] buffer = null;
File file = new File(name);
try (FileReader reader = new FileReader(file)) {
buffer = new char[(int) file.length()];
reader.read(buffer); }
catch (IOException ex) { System.out.println(ex.getMessage()); }
return new String(buffer); } }
Класс, реализующий прямое чтение и запись данныхpackage decorator.example.decorators; import java.io.*; public class FileDataSource implements DataSource { private

Слайд 9Базовый декоратор
package decorator.example.decorators;
public class DataSourceDecorator implements DataSource {
private

DataSource wrappee;
public DataSourceDecorator(DataSource source) {
this.wrappee = source; }


@Override
public void writeData(String data) {
wrappee.writeData(data); }
@Override
public String readData() {
return wrappee.readData(); } }
Базовый декораторpackage decorator.example.decorators; public class DataSourceDecorator implements DataSource { private DataSource wrappee; public DataSourceDecorator(DataSource source) { this.wrappee

Слайд 10Декоратор шифрования
package decorator.example.decorators;
import java.util.Base64;
public class EncryptionDecorator extends DataSourceDecorator

{
public EncryptionDecorator(DataSource source) { super(source); }
@Override
public void

writeData(String data) {
super.writeData(encode(data)); }
@Override
public String readData() {
return decode(super.readData()); }
public String readDecodedData() {
return decode(super.readData()); }
public String encode(String data) {
byte[] result = data.getBytes();
for (int i = 0; i < result.length; i++) {
result[i] += (byte) 1; }
return Base64.getEncoder().encodeToString(result); }
public String decode(String data) {
byte[] result = Base64.getDecoder().decode(data);
for (int i = 0; i < result.length; i++) {
result[i] -= (byte) 1; }
return new String(result); } }
Декоратор шифрованияpackage decorator.example.decorators; import java.util.Base64; public class EncryptionDecorator extends DataSourceDecorator { public EncryptionDecorator(DataSource source) { super(source); }

Слайд 11Декоратор сжатия
package decorator.example.decorators;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import

java.io.InputStream;
import java.util.Base64;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;
public

class CompressionDecorator extends DataSourceDecorator {
private int compLevel = 6;
public CompressionDecorator(DataSource source) { super(source); }
public int getCompressionLevel() { return compLevel; }
public void setCompressionLevel(int value) { compLevel = value; }
@Override
public void writeData(String data) { super.writeData(compress(data)); }
@Override
public String readData() { return decompress(super.readData()); }
Декоратор сжатияpackage decorator.example.decorators; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Base64; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream;

Слайд 12сжатие
public String compress(String stringData) {
byte[] data = stringData.getBytes();

try { ByteArrayOutputStream bout = new ByteArrayOutputStream(512);
DeflaterOutputStream dos =

new DeflaterOutputStream(bout, new Deflater(compLevel));
dos.write(data);
dos.close();
bout.close();
return Base64.getEncoder().encodeToString(bout.toByteArray()); }
catch (IOException ex) { return null; } }
public String decompress(String stringData) {
byte[] data = Base64.getDecoder().decode(stringData);
try { InputStream in = new ByteArrayInputStream(data);
InflaterInputStream iin = new InflaterInputStream(in);
ByteArrayOutputStream bout = new ByteArrayOutputStream(512);
int b;
while ((b = iin.read()) != -1) { bout.write(b); }
in.close();
iin.close();
bout.close();
return new String(bout.toByteArray()); }
catch (IOException ex) { return null; } } }

сжатие public String compress(String stringData) { byte[] data = stringData.getBytes(); try { ByteArrayOutputStream bout = new ByteArrayOutputStream(512);

Слайд 13Клиентский код
package decorator.example;
public class Demo {
public static void

main(String[] args) {
String salaryRecords = "Name,Salary\nJohn Smith,100000\nSteven Jobs,912000";
DataSourceDecorator

encoded = new CompressionDecorator( new EncryptionDecorator( new FileDataSource("out/OutputDemo.txt"))); encoded.writeData(salaryRecords);
DataSource plain = new FileDataSource("out/OutputDemo.txt");
System.out.println("- Input ----------------");
System.out.println(salaryRecords);
System.out.println("- Encoded --------------");
System.out.println(plain.readData());
System.out.println("- Decoded --------------");
System.out.println(encoded.readData()); } }
Клиентский кодpackage decorator.example; public class Demo { public static void main(String[] args) { String salaryRecords =

Слайд 14Когда использовать паттерн Декоратор?
Есть три распространенные ситуации, в которых вы

могли бы рассмотреть возможность использования этого паттерна:
Нужно добавлять функциональность к

отдельным объектам динамически и прозрачно без влияния на другие объекты.
Нужно расширить поведение класса, с которым это делать было бы непрактично. Определение класса может быть скрыто и недоступно для наследования от него, или расширение поведения класса потребовало бы огромного количества подклассов для поддержания каждой комбинации возможностей.
Расширенные возможности класса могут быть опциональными.
Когда использовать паттерн Декоратор? Есть три распространенные ситуации, в которых вы могли бы рассмотреть возможность использования этого

Слайд 15Пример Декоратора из WIKI
public interface InterfaceComponent { void doOperation(); }

class MainComponent implements InterfaceComponent {
@Override
public void doOperation() {


System.out.print("World!"); } }

abstract class Decorator implements InterfaceComponent {
protected InterfaceComponent component;
public Decorator (InterfaceComponent c) { component = c; }
@Override
public void doOperation() {
component.doOperation(); }
public void newOperation() {
System.out.println("Do Nothing"); } }
Пример Декоратора из WIKIpublic interface InterfaceComponent { void doOperation(); } class MainComponent implements InterfaceComponent { @Override public

Слайд 16Классы Декораторы
class DecoratorSpace extends Decorator {
public DecoratorSpace(InterfaceComponent c) {

super(c); }
@Override
public void doOperation() {
System.out.print(" ");
super.doOperation();

}
@Override
public void newOperation() {
System.out.println("New space operation"); } }

class DecoratorComma extends Decorator {
public DecoratorComma(InterfaceComponent c) { super(c); }
@Override
public void doOperation() { System.out.print(",");
super.doOperation(); }
@Override
public void newOperation() {
System.out.println("New comma operation"); } }
Классы Декораторыclass DecoratorSpace extends Decorator { public DecoratorSpace(InterfaceComponent c) { super(c); } @Override public void doOperation() {

Слайд 17Класс Декораторы+Main
class DecoratorHello extends Decorator {
public DecoratorHello(InterfaceComponent c) {


super(c); }
@Override
public void doOperation() {
System.out.print("Hello");
super.doOperation(); }


@Override
public void newOperation() {
System.out.println("New hello operation"); } }

class Main {
public static void main (String... s) {
Decorator c = new DecoratorHello(new DecoratorComma(new DecoratorSpace(new MainComponent())));
c.doOperation(); // Результат выполнения?
c.newOperation(); // Результат выполнения ?
} }
Класс Декораторы+Mainclass DecoratorHello extends Decorator { public DecoratorHello(InterfaceComponent c) { super(c); } @Override public void doOperation() {

Слайд 18Преимущества и недостатки
Большая гибкость, чем у наследования.
Позволяет добавлять обязанности на

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

вместо одного объекта на все случаи жизни.
Трудно конфигурировать многократно обёрнутые объекты.
Обилие крошечных классов

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

Слайд 19Отношения с другими паттернами
Адаптер предоставляет классу альтернативный интерфейс. Заместитель предоставляет

тот же интерфейс. Декоратор предоставляет расширенный интерфейс.
Адаптер меняет интерфейс существующего

объекта. Декоратор улучшает другой объект без изменения его интерфейса. Причём Декоратор поддерживает рекурсивную вложенность, чего не скажешь об Адаптере.
Цепочку обязанностей и Декоратор имеют очень похожие структуры. Оба паттерна базируются на принципе рекурсивного выполнения операции через серию связанных объектов. Но есть и несколько важных отличий.
Обработчики в Цепочке обязанностей могут выполнять произвольные действия, независимые друг от друга, а также в любой момент прерывать дальнейшую передачу по цепочке. С другой стороны Декораторы расширяют какое-то определённое действие, не ломая интерфейс базовой операции и не прерывая выполнение остальных декораторов.

Отношения с другими паттернами Адаптер предоставляет классу альтернативный интерфейс. Заместитель предоставляет тот же интерфейс. Декоратор предоставляет расширенный

Слайд 20Отношения декоратора с другими паттернами
Компоновщик и Декоратор имеют похожие структуры

классов из-за того, что оба построены на рекурсивной вложенности. Она

позволяет связать в одну структуру бесконечное количество объектов.
Декоратор оборачивает только один объект, а узел Компоновщика может иметь много детей. Декоратор добавляет вложенному объекту новую функциональность, а Компоновщик не добавляет ничего нового, но «суммирует» результаты всех своих детей.
Но они могут и сотрудничать: Компоновщик может использовать Декоратор, чтобы переопределить функции отдельных частей дерева компонентов.
Архитектура, построенная на Компоновщиках и Декораторах часто может быть улучшена за счёт внедрения Прототипа. Он позволил бы клонировать сложные структуры, а не собирать заново.
Стратегия меняет поведение объекта «изнутри», а Декоратор изменяет его «снаружи».
Декоратор и Заместитель имеют похожие структуры, но разные назначения. Они похожи тем, что оба построены на композиции и делегировании работы другому объекту. Паттерны отличаются тем, что Заместитель сам управляет жизнью сервисного объекта, а обёртывание Декораторов контролируется клиентом.
Отношения декоратора с другими паттернамиКомпоновщик и Декоратор имеют похожие структуры классов из-за того, что оба построены на

Слайд 21Шаги реализации
Убедитесь, что у в вашей задаче есть один основной

компонент и несколько опциональных дополнений или надстроек над ним.
Создайте интерфейс Компонента,

который содержал бы все общие методы для основного компонента и его дополнений.
Создайте класс Конкретного компонента и поместите в него основную бизнес-логику.
Создайте базовый класс декораторов. Он должен содержать ссылку на объект типа Компонент.
Оба класса должны реализовывать интерфейс Компонента.
Все методы Базового декоратора должны делегировать действие оборачиваемому объекту.
Создайте классы конкретных декораторов, наследуя их от Базового декоратора.
Конкретный декоратор должен выполнять свою добавочную функциональность, а затем (или перед этим) вызывать эту же операцию обёрнутого объекта.
Клиент берёт на себя ответственность за конфигурацию и порядок обёртывания объектов.

Шаги реализации Убедитесь, что у в вашей задаче есть один основной компонент и несколько опциональных дополнений или

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

ее стоимости на основе составляющих объектов реализующих интерфейс Component

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

Слайд 23Класс клиента
public class Main {
    public static void main(String[] args){
        Component computer

= new Computer();
        computer = new Keyboard(computer);
        computer = new Mouse(computer);
        computer =

new Memory(computer);
        computer = new Memory(computer);
        System.out.println("Order for my computer");
        for (String part : computer.getDescription()){
            System.out.println("Component: "+part);
        }
        System.out.println("Total cost: "+computer.getCost());
    }
}

Класс клиентаpublic class Main {    public static void main(String[] args){        Component computer = new Computer();        computer = new Keyboard(computer);        computer =

Слайд 24Интерфейсы Component и ComponentDecorator
public interface Component {
    public ArrayList getDescription();
    public double

getCost();
}

public interface ComponentDecorator extends Component {
public void setWrapped(Component

c);
}

Интерфейсы Component и ComponentDecoratorpublic interface Component {    public ArrayList getDescription();    public double getCost();}public interface ComponentDecorator extends Component {

Слайд 25Класс конкретного компонента
public class Computer implements Component {
    @Override
    public ArrayList getDescription()

{
        ArrayList arrayList = new ArrayList();
        arrayList.add("My computer");
        return arrayList;
    }
 
    @Override
    public double getCost() {
        return

33000.0;
    }
}

Класс конкретного компонентаpublic class Computer implements Component {    @Override    public ArrayList getDescription() {        ArrayList arrayList = new ArrayList();        arrayList.add(

Слайд 26Класс декоратор -клавиатура
public class Keyboard implements ComponentDecorator {

    Component wrapped;

    public Keyboard(Component

c){        setWrapped(c);    }
    @Override
    public void setWrapped(Component c) {
        this.wrapped = c;
    }
     @Override
    public ArrayList getDescription() {
        ArrayList

arrayList = wrapped.getDescription();
        arrayList.add("Logitech Keyboard K200");
        return arrayList;
    }
     @Override
    public double getCost() {
        return wrapped.getCost() + 820.;
    }
}
Класс декоратор -клавиатураpublic class Keyboard implements ComponentDecorator {    Component wrapped;    public Keyboard(Component c){        setWrapped(c);    }    @Override    public void setWrapped(Component c) {        this.wrapped = c;    }     @Override    public

Слайд 27Класс декоратор -мышь
public class Mouse implements ComponentDecorator {
    Component wrapped;
 
    public Mouse(Component

c){
        setWrapped(c);
    }
    @Override
    public void setWrapped(Component c) {
        this.wrapped = c;
    }
 
    @Override
    public ArrayList getDescription() {
        ArrayList

arrayList = wrapped.getDescription();
        arrayList.add("SteelSeries Sensei MLG 62153 Black");
        return arrayList;
    }
 
    @Override
    public double getCost() {
        return wrapped.getCost() + 7190.;
    }
}
Класс декоратор -мышьpublic class Mouse implements ComponentDecorator {    Component wrapped;     public Mouse(Component c){        setWrapped(c);    }    @Override    public void setWrapped(Component c) {        this.wrapped = c;    }     @Override    public

Слайд 28Класс декоратор -память
public class Memory implements ComponentDecorator {
    Component wrapped;
 
    public Memory(Component

c){
        setWrapped(c);
    }
 
    @Override
    public void setWrapped(Component c) {
        this.wrapped = c;
    }
 
    @Override
    public ArrayList getDescription() {
        ArrayList

arrayList = wrapped.getDescription();
        arrayList.add("Toshiba STOR.E 1TB");
        return arrayList;
    }
 
    @Override
    public double getCost() {
        return wrapped.getCost() + 4630.;
    }
}
Класс декоратор -памятьpublic class Memory implements ComponentDecorator {    Component wrapped;     public Memory(Component c){        setWrapped(c);    }     @Override    public void setWrapped(Component c) {        this.wrapped = c;    }     @Override    public

Слайд 29Литература
https://ru.wikipedia.org/wiki/Декоратор_(шаблон_проектирования)
https://refactoring.guru/ru/design-patterns/decorator

Литератураhttps://ru.wikipedia.org/wiki/Декоратор_(шаблон_проектирования)https://refactoring.guru/ru/design-patterns/decorator

Обратная связь

Если не удалось найти и скачать доклад-презентацию, Вы можете заказать его на нашем сайте. Мы постараемся найти нужный Вам материал и отправим по электронной почте. Не стесняйтесь обращаться к нам, если у вас возникли вопросы или пожелания:

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика