В шаблоне проектирования декоратора мы оборачиваем объекты одинакового типа друг в друга, а затем в цепочке вызываем одну и ту же функцию из них. Это позволяет добавить функциональность. Теперь почему бы нам не сделать то же самое не в цепи, а в цикле. Я имею в виду, что мы можем хранить все объекты в векторе (map?), И если вызывается функция, мы можем делегировать этот вызов каждому элементу вектора. Купив это, мы получим даже такое преимущество, как если бы я хотел получить доступ (чтобы получить состояние) к конкретному декоратору, я мог получить к нему прямой доступ и не добавлять общедоступную функцию к интерфейсу, так что все декораторы должны переопределять, но в большинстве им эта функция ничего не должна делать. Например, в классическом примере с окна и полосы прокрутки если я не хочу знать, заблокирована ли горизонтальная полоса прокрутки, мне нужно добавить функцию isHor horizontalScrollBarLocked в WindowDecorator
, что не имеет смысла для вертикальной полосы прокрутки и многих других декораторов тоже.
РЕДАКТИРОВАТЬ (добавив код, чтобы прояснить, что я говорю):
// the Window interface class
public interface Window {
public void draw(); // draws the Window
public String getDescription(); // returns a description of the Window
}
// extension of a simple Window without any scrollbars
class SimpleWindow implements Window {
public void draw() {
// draw window
}
public String getDescription() {
return "simple window";
}
}
// abstract decorator class - note that it implements Window
abstract class WindowDecorator implements Window {
protected Window decoratedWindow; // the Window being decorated
public WindowDecorator (Window decoratedWindow) {
this.decoratedWindow = decoratedWindow;
}
public void draw() {
decoratedWindow.draw(); //delegation
}
public String getDescription() {
return decoratedWindow.getDescription(); //delegation
}
}// the first concrete decorator which adds vertical scrollbar functionality
class VerticalScrollBarDecorator extends WindowDecorator {
public VerticalScrollBarDecorator (Window decoratedWindow) {
super(decoratedWindow);
}
@Override
public void draw() {
super.draw();
drawVerticalScrollBar();
}
private void drawVerticalScrollBar() {
// draw the vertical scrollbar
}
@Override
public String getDescription() {
return super.getDescription() + ", including vertical scrollbars";
}
}// the second concrete decorator which adds horizontal scrollbar functionality
class HorizontalScrollBarDecorator extends WindowDecorator {
public HorizontalScrollBarDecorator (Window decoratedWindow) {
super(decoratedWindow);
}
@Override
public void draw() {
super.draw();
drawHorizontalScrollBar();
}
private void drawHorizontalScrollBar() {
// draw the horizontal scrollbar
}
@Override
public String getDescription() {
return super.getDescription() + ", including horizontal scrollbars";
}
}
public class DecoratedWindowTest {
public static void main(String[] args) {
// create a decorated Window with horizontal and vertical scrollbars
Window decoratedWindow = new HorizontalScrollBarDecorator (
new VerticalScrollBarDecorator (new SimpleWindow()));
// print the Window's description
System.out.println(decoratedWindow.getDescription());
}
}
Теперь я хочу знать, заблокирована ли горизонтальная полоса прокрутки для decoratedWindow
, Что я должен делать? Мне нужно добавить isHorizontalScrollBarLocked
общественная функция в Window
и переопределить его в HorizontalScrollBarDecorator
и во всех других классах, которые реализуют Window
(в VerticalScrollBarDecorator
WindowDecorator
) право?
С другой стороны, я мог бы создать фасад, который будет представлять мое окно. В этом фасаде у меня будет список Window
объекты и эти объекты будут SimpleWindow
, VerticalScrollBarDecorator
, HorizontalScrollBarDecorator
и т. д. И если пользователь будет вызывать функцию draw
фасада, я в петле все обзвоню draw
функции Window
в списке. В противном случае, если пользователь позвонит isHorizontalScrollBarLocked
только на HorizontalScrollBarDecorator
объект.
Предлагаемое вами изменение шаблона декоратора не будет в силе. Фасад, который вы хотите реализовать, на самом деле не «украшает», так сказать, какую-либо функциональность. Позволь мне объяснить…
Рассмотрим сценарий, в котором вы хотите использовать BufferedWriter
записать байты в выходной поток. BufferedWriter
Ответственность заключается в том, чтобы дождаться накопления достаточного количества байтов, прежде чем он выполнит свою дорогостоящую операцию — запись ввода-вывода. Это decorates
нормальный поток, объединяющий несколько операций записи в пакеты.
Если бы у вас был фасад, делегаты которого звонили по всей цепочке декораторов, какой смысл использовать BufferedWriter
? Фасад не знает, в каком состоянии находится BufferedWriter
находится в, так что он не может принять вызов о том, чтобы выполнить цепочку полностью вниз.
Других решений пока нет …