Decorator设计模式:为什么调用链中的函数而不调用循环中的函数

Decorator design pattern: why call functions in chain but not in loop?

本文关键字:函数 调用 循环 设计模式 为什么 Decorator      更新时间:2023-10-16

在装饰器设计模式中,我们将相同类型的对象封装在一起,然后在链中调用它们中的相同函数。这允许添加一个功能。现在,我们为什么不做同样的事情,不是在链中,而是在循环中。我的意思是,我们可以将所有对象存储在一个向量中(map?),如果调用了一个函数,我们就可以将该调用委托给向量的每个元素。购买这样做我们将有甚至的优势,例如如果我想访问(获取状态)一个特定的装饰器,我可以直接访问它,而不向接口添加公共函数,这样所有的装饰器都应该重写,但在大多数情况下,该函数不应该做任何事情。例如,在窗口和滚动条的经典示例中,如果我不想知道水平滚动条是否被锁定,那么我需要向WindowDecorator添加isHorizontalScrollBarLocked函数,这对垂直滚动条和许多其他装饰器来说也没有意义。

编辑(添加代码以明确我所说的内容):

// 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的水平滚动条是否被锁定。我该怎么办?我需要在Window中添加isHorizontalScrollBarLocked公共函数,并在HorizontalScrollBarDecorator和所有其他实现Window的类(在VerticalScrollBarDecorator WindowDecorator中)中重写它,对吗?

另一方面,我可以创建一个立面,它将代表我的窗户。在该facade中,我将有一个Window对象的列表,这些对象将是SimpleWindowVerticalScrollBarDecoratorHorizontalScrollBarDecorator等。如果用户将调用facade的函数draw,我将在循环中调用列表中Windows的所有draw函数。否则,如果用户仅在HorizontalScrollBarDecorator对象上调用isHorizontalScrollBarLocked

您建议的对decorator模式的更改效果不佳。可以说,您想要实现的facade并没有真正"装饰"任何功能。让我解释一下。。。

考虑一个场景,您希望使用BufferedWriter将字节写入输出流。BufferedWriter的职责是等待足够的字节积累,然后再执行其昂贵的操作——写IO。它通过将几个写操作组合成批来decorates是一个正常的流。

如果您有一个facade,它在decorator链中一直被委托调用,那么BufferedWriter有什么用?facade并不真正知道BufferedWriter处于什么状态,因此它不能调用是否一直执行链。