В Java шаблоны Decorator и Proxy широко используются для улучшения функциональности объектов. Хотя оба шаблона включают в себя перенос объектов, они служат разным целям и имеют разные реализации. В этой статье мы углубимся в детали этих шаблонов, обсудим их различия и предоставим примеры кода, иллюстрирующие их использование.
Шаблон декоратора:
Шаблон «Декоратор» позволяет нам динамически добавлять новое поведение или изменять существующее поведение объекта. Он следует принципу композиции, при котором объекты оборачиваются другими объектами, имеющими тот же интерфейс. Обернутые объекты могут добавлять или изменять функциональные возможности до или после делегирования операции базовому объекту.
Пример:
Давайте рассмотрим простой пример интерфейса Shapeи его реализации, Rectangle. Мы хотим добавить возможность рисовать рамку вокруг прямоугольника без изменения существующих классов.
public interface Shape {
void draw();
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle.");
}
}
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape) {
this.decoratedShape = decoratedShape;
}
@Override
public void draw() {
decoratedShape.draw();
}
}
public class BorderDecorator extends ShapeDecorator {
public BorderDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
super.draw();
System.out.println("Adding border to the shape.");
}
}
// Usage
Shape rectangle = new Rectangle();
Shape decoratedRectangle = new BorderDecorator(rectangle);
decoratedRectangle.draw();
Выход:
Drawing a rectangle.
Adding border to the shape.
В приведенном выше примере ShapeDecoratorдействует как базовый класс декоратора, который обертывает объект Shape. BorderDecoratorрасширяет ShapeDecoratorи добавляет дополнительную функцию рисования границы.
Шаблон прокси:
Шаблон Proxy предоставляет суррогат или заполнитель для объекта и контролирует доступ к нему. Это позволяет добавлять дополнительную логику до или после доступа к реальному объекту. Прокси-объекты реализуют тот же интерфейс, что и исходный объект, и могут использоваться в качестве замены.
Пример:
Давайте рассмотрим сценарий, в котором у нас есть дорогостоящая операция ImageLoader, которая загружает изображение с диска. Мы хотим добавить прокси-уровень для кэширования загруженного изображения и избежать дорогостоящего доступа к диску для последующих запросов.
public interface Image {
void display();
}
public class ImageLoader implements Image {
private String filename;
public ImageLoader(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading image from disk: " + filename);
// Load image from disk
}
@Override
public void display() {
System.out.println("Displaying image: " + filename);
}
}
public class ImageProxy implements Image {
private ImageLoader imageLoader;
private String filename;
public ImageProxy(String filename) {
this.filename = filename;
}
@Override
public void display() {
if (imageLoader == null) {
imageLoader = new ImageLoader(filename);
}
imageLoader.display();
}
}
// Usage
Image image = new ImageProxy("image.jpg");
image.display();
Выход:
Loading image from disk: image.jpg
Displaying image: image.jpg
В приведенном выше примере ImageProxyдействует как прокси для объекта ImageLoader. Он откладывает создание ImageLoaderдо тех пор, пока не будет вызван метод display(). Такое поведение отложенной загрузки помогает оптимизировать производительность, загружая изображение с диска только тогда, когда это необходимо.
Резюме:
Шаблон «Декоратор» используется для динамического добавления или изменения поведения объекта путем его обертывания другими объектами того же интерфейса. С другой стороны, шаблон Proxy предоставляет суррогат или заполнитель для объекта и контролирует доступ к нему, добавляя дополнительную логику до или после доступа к реальному объекту.
Поняв различия между этими двумя шаблонами, вы сможете выбрать тот, который соответствует вашим требованиям и целям проектирования.